Merge pull request #600 from tr8dr/master
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 void
206 mono_reflection_init (void)
207 {
208 }
209
210 static void
211 sigbuffer_init (SigBuffer *buf, int size)
212 {
213         buf->buf = g_malloc (size);
214         buf->p = buf->buf;
215         buf->end = buf->buf + size;
216 }
217
218 static void
219 sigbuffer_make_room (SigBuffer *buf, int size)
220 {
221         if (buf->end - buf->p < size) {
222                 int new_size = buf->end - buf->buf + size + 32;
223                 char *p = g_realloc (buf->buf, new_size);
224                 size = buf->p - buf->buf;
225                 buf->buf = p;
226                 buf->p = p + size;
227                 buf->end = buf->buf + new_size;
228         }
229 }
230
231 static void
232 sigbuffer_add_value (SigBuffer *buf, guint32 val)
233 {
234         sigbuffer_make_room (buf, 6);
235         mono_metadata_encode_value (val, buf->p, &buf->p);
236 }
237
238 static void
239 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
240 {
241         sigbuffer_make_room (buf, 1);
242         buf->p [0] = val;
243         buf->p++;
244 }
245
246 static void
247 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
248 {
249         sigbuffer_make_room (buf, size);
250         memcpy (buf->p, p, size);
251         buf->p += size;
252 }
253
254 static void
255 sigbuffer_free (SigBuffer *buf)
256 {
257         g_free (buf->buf);
258 }
259
260 #ifndef DISABLE_REFLECTION_EMIT
261 /**
262  * mp_g_alloc:
263  *
264  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
265  * from the C heap.
266  */
267 static gpointer
268 image_g_malloc (MonoImage *image, guint size)
269 {
270         if (image)
271                 return mono_image_alloc (image, size);
272         else
273                 return g_malloc (size);
274 }
275 #endif /* !DISABLE_REFLECTION_EMIT */
276
277 /**
278  * image_g_alloc0:
279  *
280  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281  * from the C heap.
282  */
283 static gpointer
284 image_g_malloc0 (MonoImage *image, guint size)
285 {
286         if (image)
287                 return mono_image_alloc0 (image, size);
288         else
289                 return g_malloc0 (size);
290 }
291
292 #ifndef DISABLE_REFLECTION_EMIT
293 static char*
294 image_strdup (MonoImage *image, const char *s)
295 {
296         if (image)
297                 return mono_image_strdup (image, s);
298         else
299                 return g_strdup (s);
300 }
301 #endif
302
303 #define image_g_new(image,struct_type, n_structs)               \
304     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
305
306 #define image_g_new0(image,struct_type, n_structs)              \
307     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
308
309
310 static void
311 alloc_table (MonoDynamicTable *table, guint nrows)
312 {
313         table->rows = nrows;
314         g_assert (table->columns);
315         if (nrows + 1 >= table->alloc_rows) {
316                 while (nrows + 1 >= table->alloc_rows) {
317                         if (table->alloc_rows == 0)
318                                 table->alloc_rows = 16;
319                         else
320                                 table->alloc_rows *= 2;
321                 }
322
323                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
324         }
325 }
326
327 static void
328 make_room_in_stream (MonoDynamicStream *stream, int size)
329 {
330         if (size <= stream->alloc_size)
331                 return;
332         
333         while (stream->alloc_size <= size) {
334                 if (stream->alloc_size < 4096)
335                         stream->alloc_size = 4096;
336                 else
337                         stream->alloc_size *= 2;
338         }
339         
340         stream->data = g_realloc (stream->data, stream->alloc_size);
341 }
342
343 static guint32
344 string_heap_insert (MonoDynamicStream *sh, const char *str)
345 {
346         guint32 idx;
347         guint32 len;
348         gpointer oldkey, oldval;
349
350         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
351                 return GPOINTER_TO_UINT (oldval);
352
353         len = strlen (str) + 1;
354         idx = sh->index;
355         
356         make_room_in_stream (sh, idx + len);
357
358         /*
359          * We strdup the string even if we already copy them in sh->data
360          * so that the string pointers in the hash remain valid even if
361          * we need to realloc sh->data. We may want to avoid that later.
362          */
363         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
364         memcpy (sh->data + idx, str, len);
365         sh->index += len;
366         return idx;
367 }
368
369 static guint32
370 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
371 {
372         char *name = mono_string_to_utf8 (str);
373         guint32 idx;
374         idx = string_heap_insert (sh, name);
375         g_free (name);
376         return idx;
377 }
378
379 #ifndef DISABLE_REFLECTION_EMIT
380 static void
381 string_heap_init (MonoDynamicStream *sh)
382 {
383         sh->index = 0;
384         sh->alloc_size = 4096;
385         sh->data = g_malloc (4096);
386         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
387         string_heap_insert (sh, "");
388 }
389 #endif
390
391 static guint32
392 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
393 {
394         guint32 idx;
395         
396         make_room_in_stream (stream, stream->index + len);
397         memcpy (stream->data + stream->index, data, len);
398         idx = stream->index;
399         stream->index += len;
400         /* 
401          * align index? Not without adding an additional param that controls it since
402          * we may store a blob value in pieces.
403          */
404         return idx;
405 }
406
407 static guint32
408 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
409 {
410         guint32 idx;
411         
412         make_room_in_stream (stream, stream->index + len);
413         memset (stream->data + stream->index, 0, len);
414         idx = stream->index;
415         stream->index += len;
416         return idx;
417 }
418
419 static void
420 stream_data_align (MonoDynamicStream *stream)
421 {
422         char buf [4] = {0};
423         guint32 count = stream->index % 4;
424
425         /* we assume the stream data will be aligned */
426         if (count)
427                 mono_image_add_stream_data (stream, buf, 4 - count);
428 }
429
430 #ifndef DISABLE_REFLECTION_EMIT
431 static int
432 mono_blob_entry_hash (const char* str)
433 {
434         guint len, h;
435         const char *end;
436         len = mono_metadata_decode_blob_size (str, &str);
437         if (len > 0) {
438                 end = str + len;
439                 h = *str;
440                 for (str += 1; str < end; str++)
441                         h = (h << 5) - h + *str;
442                 return h;
443         } else {
444                 return 0;
445         }
446 }
447
448 static gboolean
449 mono_blob_entry_equal (const char *str1, const char *str2) {
450         int len, len2;
451         const char *end1;
452         const char *end2;
453         len = mono_metadata_decode_blob_size (str1, &end1);
454         len2 = mono_metadata_decode_blob_size (str2, &end2);
455         if (len != len2)
456                 return 0;
457         return memcmp (end1, end2, len) == 0;
458 }
459 #endif
460 static guint32
461 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
462 {
463         guint32 idx;
464         char *copy;
465         gpointer oldkey, oldval;
466
467         copy = g_malloc (s1+s2);
468         memcpy (copy, b1, s1);
469         memcpy (copy + s1, b2, s2);
470         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
471                 g_free (copy);
472                 idx = GPOINTER_TO_UINT (oldval);
473         } else {
474                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
475                 mono_image_add_stream_data (&assembly->blob, b2, s2);
476                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
477         }
478         return idx;
479 }
480
481 static guint32
482 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
483 {
484         char blob_size [8];
485         char *b = blob_size;
486         guint32 size = buf->p - buf->buf;
487         /* store length */
488         g_assert (size <= (buf->end - buf->buf));
489         mono_metadata_encode_value (size, b, &b);
490         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
491 }
492
493 /*
494  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
495  * dest may be misaligned.
496  */
497 static void
498 swap_with_size (char *dest, const char* val, int len, int nelem) {
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
500         int elem;
501
502         for (elem = 0; elem < nelem; ++elem) {
503                 switch (len) {
504                 case 1:
505                         *dest = *val;
506                         break;
507                 case 2:
508                         dest [0] = val [1];
509                         dest [1] = val [0];
510                         break;
511                 case 4:
512                         dest [0] = val [3];
513                         dest [1] = val [2];
514                         dest [2] = val [1];
515                         dest [3] = val [0];
516                         break;
517                 case 8:
518                         dest [0] = val [7];
519                         dest [1] = val [6];
520                         dest [2] = val [5];
521                         dest [3] = val [4];
522                         dest [4] = val [3];
523                         dest [5] = val [2];
524                         dest [6] = val [1];
525                         dest [7] = val [0];
526                         break;
527                 default:
528                         g_assert_not_reached ();
529                 }
530                 dest += len;
531                 val += len;
532         }
533 #else
534         memcpy (dest, val, len * nelem);
535 #endif
536 }
537
538 static guint32
539 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
540 {
541         char blob_size [64];
542         char *b = blob_size;
543         guint32 idx = 0, len;
544
545         len = str->length * 2;
546         mono_metadata_encode_value (len, b, &b);
547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
548         {
549                 char *swapped = g_malloc (2 * mono_string_length (str));
550                 const char *p = (const char*)mono_string_chars (str);
551
552                 swap_with_size (swapped, p, 2, mono_string_length (str));
553                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
554                 g_free (swapped);
555         }
556 #else
557         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
558 #endif
559         return idx;
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static MonoClass *
564 default_class_from_mono_type (MonoType *type)
565 {
566         switch (type->type) {
567         case MONO_TYPE_OBJECT:
568                 return mono_defaults.object_class;
569         case MONO_TYPE_VOID:
570                 return mono_defaults.void_class;
571         case MONO_TYPE_BOOLEAN:
572                 return mono_defaults.boolean_class;
573         case MONO_TYPE_CHAR:
574                 return mono_defaults.char_class;
575         case MONO_TYPE_I1:
576                 return mono_defaults.sbyte_class;
577         case MONO_TYPE_U1:
578                 return mono_defaults.byte_class;
579         case MONO_TYPE_I2:
580                 return mono_defaults.int16_class;
581         case MONO_TYPE_U2:
582                 return mono_defaults.uint16_class;
583         case MONO_TYPE_I4:
584                 return mono_defaults.int32_class;
585         case MONO_TYPE_U4:
586                 return mono_defaults.uint32_class;
587         case MONO_TYPE_I:
588                 return mono_defaults.int_class;
589         case MONO_TYPE_U:
590                 return mono_defaults.uint_class;
591         case MONO_TYPE_I8:
592                 return mono_defaults.int64_class;
593         case MONO_TYPE_U8:
594                 return mono_defaults.uint64_class;
595         case MONO_TYPE_R4:
596                 return mono_defaults.single_class;
597         case MONO_TYPE_R8:
598                 return mono_defaults.double_class;
599         case MONO_TYPE_STRING:
600                 return mono_defaults.string_class;
601         default:
602                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
603                 g_assert_not_reached ();
604         }
605         
606         return NULL;
607 }
608 #endif
609
610 /*
611  * mono_class_get_ref_info:
612  *
613  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
614  */
615 gpointer
616 mono_class_get_ref_info (MonoClass *klass)
617 {
618         if (klass->ref_info_handle == 0)
619                 return NULL;
620         else
621                 return mono_gchandle_get_target (klass->ref_info_handle);
622 }
623
624 void
625 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
626 {
627         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
628         g_assert (klass->ref_info_handle != 0);
629 }
630
631 void
632 mono_class_free_ref_info (MonoClass *klass)
633 {
634         if (klass->ref_info_handle) {
635                 mono_gchandle_free (klass->ref_info_handle);
636                 klass->ref_info_handle = 0;
637         }
638 }
639
640 static void
641 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
642 {
643         int i;
644         MonoGenericInst *class_inst;
645         MonoClass *klass;
646
647         g_assert (gclass);
648
649         class_inst = gclass->context.class_inst;
650
651         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
652         klass = gclass->container_class;
653         sigbuffer_add_value (buf, klass->byval_arg.type);
654         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
655
656         sigbuffer_add_value (buf, class_inst->type_argc);
657         for (i = 0; i < class_inst->type_argc; ++i)
658                 encode_type (assembly, class_inst->type_argv [i], buf);
659
660 }
661
662 static void
663 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
664 {
665         if (!type) {
666                 g_assert_not_reached ();
667                 return;
668         }
669                 
670         if (type->byref)
671                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
672
673         switch (type->type){
674         case MONO_TYPE_VOID:
675         case MONO_TYPE_BOOLEAN:
676         case MONO_TYPE_CHAR:
677         case MONO_TYPE_I1:
678         case MONO_TYPE_U1:
679         case MONO_TYPE_I2:
680         case MONO_TYPE_U2:
681         case MONO_TYPE_I4:
682         case MONO_TYPE_U4:
683         case MONO_TYPE_I8:
684         case MONO_TYPE_U8:
685         case MONO_TYPE_R4:
686         case MONO_TYPE_R8:
687         case MONO_TYPE_I:
688         case MONO_TYPE_U:
689         case MONO_TYPE_STRING:
690         case MONO_TYPE_OBJECT:
691         case MONO_TYPE_TYPEDBYREF:
692                 sigbuffer_add_value (buf, type->type);
693                 break;
694         case MONO_TYPE_PTR:
695                 sigbuffer_add_value (buf, type->type);
696                 encode_type (assembly, type->data.type, buf);
697                 break;
698         case MONO_TYPE_SZARRAY:
699                 sigbuffer_add_value (buf, type->type);
700                 encode_type (assembly, &type->data.klass->byval_arg, buf);
701                 break;
702         case MONO_TYPE_VALUETYPE:
703         case MONO_TYPE_CLASS: {
704                 MonoClass *k = mono_class_from_mono_type (type);
705
706                 if (k->generic_container) {
707                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
708                         encode_generic_class (assembly, gclass, buf);
709                 } else {
710                         /*
711                          * Make sure we use the correct type.
712                          */
713                         sigbuffer_add_value (buf, k->byval_arg.type);
714                         /*
715                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
716                          * otherwise two typerefs could point to the same type, leading to
717                          * verification errors.
718                          */
719                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
720                 }
721                 break;
722         }
723         case MONO_TYPE_ARRAY:
724                 sigbuffer_add_value (buf, type->type);
725                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
726                 sigbuffer_add_value (buf, type->data.array->rank);
727                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
728                 sigbuffer_add_value (buf, 0);
729                 break;
730         case MONO_TYPE_GENERICINST:
731                 encode_generic_class (assembly, type->data.generic_class, buf);
732                 break;
733         case MONO_TYPE_VAR:
734         case MONO_TYPE_MVAR:
735                 sigbuffer_add_value (buf, type->type);
736                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
737                 break;
738         default:
739                 g_error ("need to encode type %x", type->type);
740         }
741 }
742
743 static void
744 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
745 {
746         if (!type) {
747                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
748                 return;
749         }
750
751         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
752 }
753
754 static void
755 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
756 {
757         int i;
758
759         if (modreq) {
760                 for (i = 0; i < mono_array_length (modreq); ++i) {
761                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
762                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
763                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
764                 }
765         }
766         if (modopt) {
767                 for (i = 0; i < mono_array_length (modopt); ++i) {
768                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
769                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
770                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
771                 }
772         }
773 }
774
775 #ifndef DISABLE_REFLECTION_EMIT
776 static guint32
777 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
778 {
779         SigBuffer buf;
780         int i;
781         guint32 nparams =  sig->param_count;
782         guint32 idx;
783
784         if (!assembly->save)
785                 return 0;
786
787         sigbuffer_init (&buf, 32);
788         /*
789          * FIXME: vararg, explicit_this, differenc call_conv values...
790          */
791         idx = sig->call_convention;
792         if (sig->hasthis)
793                 idx |= 0x20; /* hasthis */
794         if (sig->generic_param_count)
795                 idx |= 0x10; /* generic */
796         sigbuffer_add_byte (&buf, idx);
797         if (sig->generic_param_count)
798                 sigbuffer_add_value (&buf, sig->generic_param_count);
799         sigbuffer_add_value (&buf, nparams);
800         encode_type (assembly, sig->ret, &buf);
801         for (i = 0; i < nparams; ++i) {
802                 if (i == sig->sentinelpos)
803                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804                 encode_type (assembly, sig->params [i], &buf);
805         }
806         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807         sigbuffer_free (&buf);
808         return idx;
809 }
810 #endif
811
812 static guint32
813 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
814 {
815         /*
816          * FIXME: reuse code from method_encode_signature().
817          */
818         SigBuffer buf;
819         int i;
820         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
821         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
822         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
823         guint32 idx;
824
825         sigbuffer_init (&buf, 32);
826         /* LAMESPEC: all the call conv spec is foobared */
827         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
828         if (mb->call_conv & 2)
829                 idx |= 0x5; /* vararg */
830         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
831                 idx |= 0x20; /* hasthis */
832         if (ngparams)
833                 idx |= 0x10; /* generic */
834         sigbuffer_add_byte (&buf, idx);
835         if (ngparams)
836                 sigbuffer_add_value (&buf, ngparams);
837         sigbuffer_add_value (&buf, nparams + notypes);
838         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
839         encode_reflection_type (assembly, mb->rtype, &buf);
840         for (i = 0; i < nparams; ++i) {
841                 MonoArray *modreq = NULL;
842                 MonoArray *modopt = NULL;
843                 MonoReflectionType *pt;
844
845                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
846                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
847                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
848                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
849                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
850                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
851                 encode_reflection_type (assembly, pt, &buf);
852         }
853         if (notypes)
854                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
855         for (i = 0; i < notypes; ++i) {
856                 MonoReflectionType *pt;
857
858                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
859                 encode_reflection_type (assembly, pt, &buf);
860         }
861
862         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
863         sigbuffer_free (&buf);
864         return idx;
865 }
866
867 static guint32
868 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
869 {
870         MonoDynamicTable *table;
871         guint32 *values;
872         guint32 idx, sig_idx;
873         guint nl = mono_array_length (ilgen->locals);
874         SigBuffer buf;
875         int i;
876
877         sigbuffer_init (&buf, 32);
878         sigbuffer_add_value (&buf, 0x07);
879         sigbuffer_add_value (&buf, nl);
880         for (i = 0; i < nl; ++i) {
881                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
882                 
883                 if (lb->is_pinned)
884                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
885                 
886                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
887         }
888         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
889         sigbuffer_free (&buf);
890
891         if (assembly->standalonesig_cache == NULL)
892                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
893         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
894         if (idx)
895                 return idx;
896
897         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
898         idx = table->next_idx ++;
899         table->rows ++;
900         alloc_table (table, table->rows);
901         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
902
903         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
904
905         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
906
907         return idx;
908 }
909
910 static guint32
911 method_count_clauses (MonoReflectionILGen *ilgen)
912 {
913         guint32 num_clauses = 0;
914         int i;
915
916         MonoILExceptionInfo *ex_info;
917         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
918                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
919                 if (ex_info->handlers)
920                         num_clauses += mono_array_length (ex_info->handlers);
921                 else
922                         num_clauses++;
923         }
924
925         return num_clauses;
926 }
927
928 #ifndef DISABLE_REFLECTION_EMIT
929 static MonoExceptionClause*
930 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
931 {
932         MonoExceptionClause *clauses;
933         MonoExceptionClause *clause;
934         MonoILExceptionInfo *ex_info;
935         MonoILExceptionBlock *ex_block;
936         guint32 finally_start;
937         int i, j, clause_index;;
938
939         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
940
941         clause_index = 0;
942         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
943                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
944                 finally_start = ex_info->start + ex_info->len;
945                 if (!ex_info->handlers)
946                         continue;
947                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
948                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
949                         clause = &(clauses [clause_index]);
950
951                         clause->flags = ex_block->type;
952                         clause->try_offset = ex_info->start;
953
954                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
955                                 clause->try_len = finally_start - ex_info->start;
956                         else
957                                 clause->try_len = ex_info->len;
958                         clause->handler_offset = ex_block->start;
959                         clause->handler_len = ex_block->len;
960                         if (ex_block->extype) {
961                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
962                         } else {
963                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
964                                         clause->data.filter_offset = ex_block->filter_offset;
965                                 else
966                                         clause->data.filter_offset = 0;
967                         }
968                         finally_start = ex_block->start + ex_block->len;
969
970                         clause_index ++;
971                 }
972         }
973
974         return clauses;
975 }
976 #endif /* !DISABLE_REFLECTION_EMIT */
977
978 static guint32
979 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
980 {
981         char flags = 0;
982         guint32 idx;
983         guint32 code_size;
984         gint32 max_stack, i;
985         gint32 num_locals = 0;
986         gint32 num_exception = 0;
987         gint maybe_small;
988         guint32 fat_flags;
989         char fat_header [12];
990         guint32 int_value;
991         guint16 short_value;
992         guint32 local_sig = 0;
993         guint32 header_size = 12;
994         MonoArray *code;
995
996         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
997                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
998                 return 0;
999
1000         /*if (mb->name)
1001                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1002         if (mb->ilgen) {
1003                 code = mb->ilgen->code;
1004                 code_size = mb->ilgen->code_len;
1005                 max_stack = mb->ilgen->max_stack;
1006                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1007                 if (mb->ilgen->ex_handlers)
1008                         num_exception = method_count_clauses (mb->ilgen);
1009         } else {
1010                 code = mb->code;
1011                 if (code == NULL){
1012                         char *name = mono_string_to_utf8 (mb->name);
1013                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1014                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1015                         g_free (str);
1016                         g_free (name);
1017                         mono_raise_exception (exception);
1018                 }
1019
1020                 code_size = mono_array_length (code);
1021                 max_stack = 8; /* we probably need to run a verifier on the code... */
1022         }
1023
1024         stream_data_align (&assembly->code);
1025
1026         /* check for exceptions, maxstack, locals */
1027         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1028         if (maybe_small) {
1029                 if (code_size < 64 && !(code_size & 1)) {
1030                         flags = (code_size << 2) | 0x2;
1031                 } else if (code_size < 32 && (code_size & 1)) {
1032                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1033                 } else {
1034                         goto fat_header;
1035                 }
1036                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1037                 /* add to the fixup todo list */
1038                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1039                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1040                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1041                 return assembly->text_rva + idx;
1042         } 
1043 fat_header:
1044         if (num_locals)
1045                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1046         /* 
1047          * FIXME: need to set also the header size in fat_flags.
1048          * (and more sects and init locals flags)
1049          */
1050         fat_flags =  0x03;
1051         if (num_exception)
1052                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1053         if (mb->init_locals)
1054                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1055         fat_header [0] = fat_flags;
1056         fat_header [1] = (header_size / 4 ) << 4;
1057         short_value = GUINT16_TO_LE (max_stack);
1058         memcpy (fat_header + 2, &short_value, 2);
1059         int_value = GUINT32_TO_LE (code_size);
1060         memcpy (fat_header + 4, &int_value, 4);
1061         int_value = GUINT32_TO_LE (local_sig);
1062         memcpy (fat_header + 8, &int_value, 4);
1063         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1064         /* add to the fixup todo list */
1065         if (mb->ilgen && mb->ilgen->num_token_fixups)
1066                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1067         
1068         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1069         if (num_exception) {
1070                 unsigned char sheader [4];
1071                 MonoILExceptionInfo * ex_info;
1072                 MonoILExceptionBlock * ex_block;
1073                 int j;
1074
1075                 stream_data_align (&assembly->code);
1076                 /* always use fat format for now */
1077                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1078                 num_exception *= 6 * sizeof (guint32);
1079                 num_exception += 4; /* include the size of the header */
1080                 sheader [1] = num_exception & 0xff;
1081                 sheader [2] = (num_exception >> 8) & 0xff;
1082                 sheader [3] = (num_exception >> 16) & 0xff;
1083                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1084                 /* fat header, so we are already aligned */
1085                 /* reverse order */
1086                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1087                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1088                         if (ex_info->handlers) {
1089                                 int finally_start = ex_info->start + ex_info->len;
1090                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1091                                         guint32 val;
1092                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1093                                         /* the flags */
1094                                         val = GUINT32_TO_LE (ex_block->type);
1095                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1096                                         /* try offset */
1097                                         val = GUINT32_TO_LE (ex_info->start);
1098                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1099                                         /* need fault, too, probably */
1100                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1101                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1102                                         else
1103                                                 val = GUINT32_TO_LE (ex_info->len);
1104                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105                                         /* handler offset */
1106                                         val = GUINT32_TO_LE (ex_block->start);
1107                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108                                         /* handler len */
1109                                         val = GUINT32_TO_LE (ex_block->len);
1110                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1111                                         finally_start = ex_block->start + ex_block->len;
1112                                         if (ex_block->extype) {
1113                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1114                                         } else {
1115                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1116                                                         val = ex_block->filter_offset;
1117                                                 else
1118                                                         val = 0;
1119                                         }
1120                                         val = GUINT32_TO_LE (val);
1121                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1123                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1124                                 }
1125                         } else {
1126                                 g_error ("No clauses for ex info block %d", i);
1127                         }
1128                 }
1129         }
1130         return assembly->text_rva + idx;
1131 }
1132
1133 static guint32
1134 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1135 {
1136         int i;
1137         MonoDynamicTable *table;
1138         guint32 *values;
1139         
1140         table = &assembly->tables [table_idx];
1141
1142         g_assert (col < table->columns);
1143
1144         values = table->values + table->columns;
1145         for (i = 1; i <= table->rows; ++i) {
1146                 if (values [col] == token)
1147                         return i;
1148                 values += table->columns;
1149         }
1150         return 0;
1151 }
1152
1153 /*
1154  * LOCKING: Acquires the loader lock. 
1155  */
1156 static MonoCustomAttrInfo*
1157 lookup_custom_attr (MonoImage *image, gpointer member)
1158 {
1159         MonoCustomAttrInfo* res;
1160
1161         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1162
1163         if (!res)
1164                 return NULL;
1165
1166         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1167         res->cached = 0;
1168         return res;
1169 }
1170
1171 static gboolean
1172 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1173 {
1174         /* FIXME: Need to do more checks */
1175         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1176                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1177
1178                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1179                         return FALSE;
1180         }
1181
1182         return TRUE;
1183 }
1184
1185 static MonoCustomAttrInfo*
1186 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1187 {
1188         int i, index, count, not_visible;
1189         MonoCustomAttrInfo *ainfo;
1190         MonoReflectionCustomAttr *cattr;
1191
1192         if (!cattrs)
1193                 return NULL;
1194         /* FIXME: check in assembly the Run flag is set */
1195
1196         count = mono_array_length (cattrs);
1197
1198         /* Skip nonpublic attributes since MS.NET seems to do the same */
1199         /* FIXME: This needs to be done more globally */
1200         not_visible = 0;
1201         for (i = 0; i < count; ++i) {
1202                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1203                 if (!custom_attr_visible (image, cattr))
1204                         not_visible ++;
1205         }
1206         count -= not_visible;
1207
1208         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1209
1210         ainfo->image = image;
1211         ainfo->num_attrs = count;
1212         ainfo->cached = alloc_img != NULL;
1213         index = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (custom_attr_visible (image, cattr)) {
1217                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1218                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1219                         ainfo->attrs [index].ctor = cattr->ctor->method;
1220                         ainfo->attrs [index].data = saved;
1221                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1222                         index ++;
1223                 }
1224         }
1225
1226         return ainfo;
1227 }
1228
1229 #ifndef DISABLE_REFLECTION_EMIT
1230 /*
1231  * LOCKING: Acquires the loader lock. 
1232  */
1233 static void
1234 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1235 {
1236         MonoCustomAttrInfo *ainfo, *tmp;
1237
1238         if (!cattrs || !mono_array_length (cattrs))
1239                 return;
1240
1241         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1242
1243         mono_loader_lock ();
1244         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1245         if (tmp)
1246                 mono_custom_attrs_free (tmp);
1247         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1248         mono_loader_unlock ();
1249
1250 }
1251 #endif
1252
1253 void
1254 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1255 {
1256         if (!ainfo->cached)
1257                 g_free (ainfo);
1258 }
1259
1260 /*
1261  * idx is the table index of the object
1262  * type is one of MONO_CUSTOM_ATTR_*
1263  */
1264 static void
1265 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1266 {
1267         MonoDynamicTable *table;
1268         MonoReflectionCustomAttr *cattr;
1269         guint32 *values;
1270         guint32 count, i, token;
1271         char blob_size [6];
1272         char *p = blob_size;
1273         
1274         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1275         if (!cattrs)
1276                 return;
1277         count = mono_array_length (cattrs);
1278         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1279         table->rows += count;
1280         alloc_table (table, table->rows);
1281         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1282         idx <<= MONO_CUSTOM_ATTR_BITS;
1283         idx |= type;
1284         for (i = 0; i < count; ++i) {
1285                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1286                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1287                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1288                 type = mono_metadata_token_index (token);
1289                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1290                 switch (mono_metadata_token_table (token)) {
1291                 case MONO_TABLE_METHOD:
1292                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1293                         /*
1294                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1295                          * method, not the one returned by mono_image_create_token ().
1296                          */
1297                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1298                         break;
1299                 case MONO_TABLE_MEMBERREF:
1300                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1301                         break;
1302                 default:
1303                         g_warning ("got wrong token in custom attr");
1304                         continue;
1305                 }
1306                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1307                 p = blob_size;
1308                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1309                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1310                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1311                 values += MONO_CUSTOM_ATTR_SIZE;
1312                 ++table->next_idx;
1313         }
1314 }
1315
1316 static void
1317 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1318 {
1319         MonoDynamicTable *table;
1320         guint32 *values;
1321         guint32 count, i, idx;
1322         MonoReflectionPermissionSet *perm;
1323
1324         if (!permissions)
1325                 return;
1326
1327         count = mono_array_length (permissions);
1328         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1329         table->rows += count;
1330         alloc_table (table, table->rows);
1331
1332         for (i = 0; i < mono_array_length (permissions); ++i) {
1333                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1334
1335                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1336
1337                 idx = mono_metadata_token_index (parent_token);
1338                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1339                 switch (mono_metadata_token_table (parent_token)) {
1340                 case MONO_TABLE_TYPEDEF:
1341                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1342                         break;
1343                 case MONO_TABLE_METHOD:
1344                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1345                         break;
1346                 case MONO_TABLE_ASSEMBLY:
1347                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1348                         break;
1349                 default:
1350                         g_assert_not_reached ();
1351                 }
1352
1353                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1354                 values [MONO_DECL_SECURITY_PARENT] = idx;
1355                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1356
1357                 ++table->next_idx;
1358         }
1359 }
1360
1361 /*
1362  * Fill in the MethodDef and ParamDef tables for a method.
1363  * This is used for both normal methods and constructors.
1364  */
1365 static void
1366 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1367 {
1368         MonoDynamicTable *table;
1369         guint32 *values;
1370         guint i, count;
1371
1372         /* room in this table is already allocated */
1373         table = &assembly->tables [MONO_TABLE_METHOD];
1374         *mb->table_idx = table->next_idx ++;
1375         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1376         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1377         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1378         values [MONO_METHOD_FLAGS] = mb->attrs;
1379         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1380         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1381         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1382         
1383         table = &assembly->tables [MONO_TABLE_PARAM];
1384         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1385
1386         mono_image_add_decl_security (assembly, 
1387                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1388
1389         if (mb->pinfo) {
1390                 MonoDynamicTable *mtable;
1391                 guint32 *mvalues;
1392                 
1393                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1394                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1395                 
1396                 count = 0;
1397                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1398                         if (mono_array_get (mb->pinfo, gpointer, i))
1399                                 count++;
1400                 }
1401                 table->rows += count;
1402                 alloc_table (table, table->rows);
1403                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1404                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1405                         MonoReflectionParamBuilder *pb;
1406                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1407                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1408                                 values [MONO_PARAM_SEQUENCE] = i;
1409                                 if (pb->name != NULL) {
1410                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1411                                 } else {
1412                                         values [MONO_PARAM_NAME] = 0;
1413                                 }
1414                                 values += MONO_PARAM_SIZE;
1415                                 if (pb->marshal_info) {
1416                                         mtable->rows++;
1417                                         alloc_table (mtable, mtable->rows);
1418                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1419                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1420                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1421                                 }
1422                                 pb->table_idx = table->next_idx++;
1423                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1424                                         guint32 field_type = 0;
1425                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1426                                         mtable->rows ++;
1427                                         alloc_table (mtable, mtable->rows);
1428                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1429                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1430                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1431                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1432                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1433                                 }
1434                         }
1435                 }
1436         }
1437 }
1438
1439 #ifndef DISABLE_REFLECTION_EMIT
1440 static void
1441 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1442 {
1443         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1444
1445         rmb->ilgen = mb->ilgen;
1446         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1447         rmb->parameters = mb->parameters;
1448         rmb->generic_params = mb->generic_params;
1449         rmb->generic_container = mb->generic_container;
1450         rmb->opt_types = NULL;
1451         rmb->pinfo = mb->pinfo;
1452         rmb->attrs = mb->attrs;
1453         rmb->iattrs = mb->iattrs;
1454         rmb->call_conv = mb->call_conv;
1455         rmb->code = mb->code;
1456         rmb->type = mb->type;
1457         rmb->name = mb->name;
1458         rmb->table_idx = &mb->table_idx;
1459         rmb->init_locals = mb->init_locals;
1460         rmb->skip_visibility = FALSE;
1461         rmb->return_modreq = mb->return_modreq;
1462         rmb->return_modopt = mb->return_modopt;
1463         rmb->param_modreq = mb->param_modreq;
1464         rmb->param_modopt = mb->param_modopt;
1465         rmb->permissions = mb->permissions;
1466         rmb->mhandle = mb->mhandle;
1467         rmb->nrefs = 0;
1468         rmb->refs = NULL;
1469
1470         if (mb->dll) {
1471                 rmb->charset = mb->charset;
1472                 rmb->extra_flags = mb->extra_flags;
1473                 rmb->native_cc = mb->native_cc;
1474                 rmb->dllentry = mb->dllentry;
1475                 rmb->dll = mb->dll;
1476         }
1477 }
1478
1479 static void
1480 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1481 {
1482         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1483
1484         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1485
1486         rmb->ilgen = mb->ilgen;
1487         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1488         rmb->parameters = mb->parameters;
1489         rmb->generic_params = NULL;
1490         rmb->generic_container = NULL;
1491         rmb->opt_types = NULL;
1492         rmb->pinfo = mb->pinfo;
1493         rmb->attrs = mb->attrs;
1494         rmb->iattrs = mb->iattrs;
1495         rmb->call_conv = mb->call_conv;
1496         rmb->code = NULL;
1497         rmb->type = mb->type;
1498         rmb->name = mono_string_new (mono_domain_get (), name);
1499         rmb->table_idx = &mb->table_idx;
1500         rmb->init_locals = mb->init_locals;
1501         rmb->skip_visibility = FALSE;
1502         rmb->return_modreq = NULL;
1503         rmb->return_modopt = NULL;
1504         rmb->param_modreq = mb->param_modreq;
1505         rmb->param_modopt = mb->param_modopt;
1506         rmb->permissions = mb->permissions;
1507         rmb->mhandle = mb->mhandle;
1508         rmb->nrefs = 0;
1509         rmb->refs = NULL;
1510 }
1511
1512 static void
1513 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1514 {
1515         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1516
1517         rmb->ilgen = mb->ilgen;
1518         rmb->rtype = mb->rtype;
1519         rmb->parameters = mb->parameters;
1520         rmb->generic_params = NULL;
1521         rmb->generic_container = NULL;
1522         rmb->opt_types = NULL;
1523         rmb->pinfo = NULL;
1524         rmb->attrs = mb->attrs;
1525         rmb->iattrs = 0;
1526         rmb->call_conv = mb->call_conv;
1527         rmb->code = NULL;
1528         rmb->type = (MonoObject *) mb->owner;
1529         rmb->name = mb->name;
1530         rmb->table_idx = NULL;
1531         rmb->init_locals = mb->init_locals;
1532         rmb->skip_visibility = mb->skip_visibility;
1533         rmb->return_modreq = NULL;
1534         rmb->return_modopt = NULL;
1535         rmb->param_modreq = NULL;
1536         rmb->param_modopt = NULL;
1537         rmb->permissions = NULL;
1538         rmb->mhandle = mb->mhandle;
1539         rmb->nrefs = 0;
1540         rmb->refs = NULL;
1541 }       
1542 #endif
1543
1544 static void
1545 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1546 {
1547         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1548         MonoDynamicTable *table;
1549         guint32 *values;
1550         guint32 tok;
1551         MonoReflectionMethod *m;
1552         int i;
1553
1554         if (!mb->override_methods)
1555                 return;
1556
1557         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1558                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1559
1560                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1561                 table->rows ++;
1562                 alloc_table (table, table->rows);
1563                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1564                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1565                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1566
1567                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1568                 switch (mono_metadata_token_table (tok)) {
1569                 case MONO_TABLE_MEMBERREF:
1570                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1571                         break;
1572                 case MONO_TABLE_METHOD:
1573                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1574                         break;
1575                 default:
1576                         g_assert_not_reached ();
1577                 }
1578                 values [MONO_METHODIMPL_DECLARATION] = tok;
1579         }
1580 }
1581
1582 #ifndef DISABLE_REFLECTION_EMIT
1583 static void
1584 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1585 {
1586         MonoDynamicTable *table;
1587         guint32 *values;
1588         ReflectionMethodBuilder rmb;
1589         int i;
1590
1591         reflection_methodbuilder_from_method_builder (&rmb, mb);
1592
1593         mono_image_basic_method (&rmb, assembly);
1594         mb->table_idx = *rmb.table_idx;
1595
1596         if (mb->dll) { /* It's a P/Invoke method */
1597                 guint32 moduleref;
1598                 /* map CharSet values to on-disk values */
1599                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1600                 int extra_flags = mb->extra_flags;
1601                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1602                 table->rows ++;
1603                 alloc_table (table, table->rows);
1604                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1605                 
1606                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1607                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1608                 if (mb->dllentry)
1609                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1610                 else
1611                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1612                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1613                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1614                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1615                         table->rows ++;
1616                         alloc_table (table, table->rows);
1617                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1618                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1619                 }
1620         }
1621
1622         if (mb->generic_params) {
1623                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1624                 table->rows += mono_array_length (mb->generic_params);
1625                 alloc_table (table, table->rows);
1626                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1627                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1628
1629                         mono_image_get_generic_param_info (
1630                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1631                 }
1632         }
1633
1634 }
1635
1636 static void
1637 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1638 {
1639         ReflectionMethodBuilder rmb;
1640
1641         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1642
1643         mono_image_basic_method (&rmb, assembly);
1644         mb->table_idx = *rmb.table_idx;
1645 }
1646 #endif
1647
1648 static char*
1649 type_get_fully_qualified_name (MonoType *type)
1650 {
1651         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1652 }
1653
1654 static char*
1655 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1656         MonoClass *klass;
1657         MonoAssembly *ta;
1658
1659         klass = mono_class_from_mono_type (type);
1660         if (!klass) 
1661                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1662         ta = klass->image->assembly;
1663         if (ta->dynamic || (ta == ass)) {
1664                 if (klass->generic_class || klass->generic_container)
1665                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1666                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1667                 else
1668                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1669         }
1670
1671         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1672 }
1673
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 /*field_image is the image to which the eventual custom mods have been encoded against*/
1676 static guint32
1677 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1678 {
1679         SigBuffer buf;
1680         guint32 idx, i, token;
1681
1682         if (!assembly->save)
1683                 return 0;
1684
1685         sigbuffer_init (&buf, 32);
1686         
1687         sigbuffer_add_value (&buf, 0x06);
1688         /* encode custom attributes before the type */
1689         if (type->num_mods) {
1690                 for (i = 0; i < type->num_mods; ++i) {
1691                         if (field_image) {
1692                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1693                                 g_assert (class);
1694                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1695                         } else {
1696                                 token = type->modifiers [i].token;
1697                         }
1698
1699                         if (type->modifiers [i].required)
1700                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1701                         else
1702                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1703
1704                         sigbuffer_add_value (&buf, token);
1705                 }
1706         }
1707         encode_type (assembly, type, &buf);
1708         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1709         sigbuffer_free (&buf);
1710         return idx;
1711 }
1712 #endif
1713
1714 static guint32
1715 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1716 {
1717         SigBuffer buf;
1718         guint32 idx;
1719         guint32 typespec = 0;
1720         MonoType *type;
1721         MonoClass *class;
1722
1723         init_type_builder_generics (fb->type);
1724
1725         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1726         class = mono_class_from_mono_type (type);
1727
1728         sigbuffer_init (&buf, 32);
1729         
1730         sigbuffer_add_value (&buf, 0x06);
1731         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1732         /* encode custom attributes before the type */
1733
1734         if (class->generic_container)
1735                 typespec = create_typespec (assembly, type);
1736
1737         if (typespec) {
1738                 MonoGenericClass *gclass;
1739                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1740                 encode_generic_class (assembly, gclass, &buf);
1741         } else {
1742                 encode_type (assembly, type, &buf);
1743         }
1744         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1745         sigbuffer_free (&buf);
1746         return idx;
1747 }
1748
1749 static guint32
1750 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1751         char blob_size [64];
1752         char *b = blob_size;
1753         char *p, *box_val;
1754         char* buf;
1755         guint32 idx = 0, len = 0, dummy = 0;
1756
1757         p = buf = g_malloc (64);
1758         if (!val) {
1759                 *ret_type = MONO_TYPE_CLASS;
1760                 len = 4;
1761                 box_val = (char*)&dummy;
1762         } else {
1763                 box_val = ((char*)val) + sizeof (MonoObject);
1764                 *ret_type = val->vtable->klass->byval_arg.type;
1765         }
1766 handle_enum:
1767         switch (*ret_type) {
1768         case MONO_TYPE_BOOLEAN:
1769         case MONO_TYPE_U1:
1770         case MONO_TYPE_I1:
1771                 len = 1;
1772                 break;
1773         case MONO_TYPE_CHAR:
1774         case MONO_TYPE_U2:
1775         case MONO_TYPE_I2:
1776                 len = 2;
1777                 break;
1778         case MONO_TYPE_U4:
1779         case MONO_TYPE_I4:
1780         case MONO_TYPE_R4:
1781                 len = 4;
1782                 break;
1783         case MONO_TYPE_U8:
1784         case MONO_TYPE_I8:
1785                 len = 8;
1786                 break;
1787         case MONO_TYPE_R8:
1788                 len = 8;
1789                 break;
1790         case MONO_TYPE_VALUETYPE: {
1791                 MonoClass *klass = val->vtable->klass;
1792                 
1793                 if (klass->enumtype) {
1794                         *ret_type = mono_class_enum_basetype (klass)->type;
1795                         goto handle_enum;
1796                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1797                         len = 8;
1798                 } else 
1799                         g_error ("we can't encode valuetypes, we should have never reached this line");
1800                 break;
1801         }
1802         case MONO_TYPE_CLASS:
1803                 break;
1804         case MONO_TYPE_STRING: {
1805                 MonoString *str = (MonoString*)val;
1806                 /* there is no signature */
1807                 len = str->length * 2;
1808                 mono_metadata_encode_value (len, b, &b);
1809 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1810                 {
1811                         char *swapped = g_malloc (2 * mono_string_length (str));
1812                         const char *p = (const char*)mono_string_chars (str);
1813
1814                         swap_with_size (swapped, p, 2, mono_string_length (str));
1815                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1816                         g_free (swapped);
1817                 }
1818 #else
1819                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1820 #endif
1821
1822                 g_free (buf);
1823                 return idx;
1824         }
1825         case MONO_TYPE_GENERICINST:
1826                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1827                 goto handle_enum;
1828         default:
1829                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1830         }
1831
1832         /* there is no signature */
1833         mono_metadata_encode_value (len, b, &b);
1834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1835         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1836         swap_with_size (blob_size, box_val, len, 1);
1837         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1838 #else
1839         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1840 #endif
1841
1842         g_free (buf);
1843         return idx;
1844 }
1845
1846 static guint32
1847 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1848         char *str;
1849         SigBuffer buf;
1850         guint32 idx, len;
1851
1852         sigbuffer_init (&buf, 32);
1853
1854         sigbuffer_add_value (&buf, minfo->type);
1855
1856         switch (minfo->type) {
1857         case MONO_NATIVE_BYVALTSTR:
1858         case MONO_NATIVE_BYVALARRAY:
1859                 sigbuffer_add_value (&buf, minfo->count);
1860                 break;
1861         case MONO_NATIVE_LPARRAY:
1862                 if (minfo->eltype || minfo->has_size) {
1863                         sigbuffer_add_value (&buf, minfo->eltype);
1864                         if (minfo->has_size) {
1865                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1866                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1867
1868                                 /* LAMESPEC: ElemMult is undocumented */
1869                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1870                         }
1871                 }
1872                 break;
1873         case MONO_NATIVE_SAFEARRAY:
1874                 if (minfo->eltype)
1875                         sigbuffer_add_value (&buf, minfo->eltype);
1876                 break;
1877         case MONO_NATIVE_CUSTOM:
1878                 if (minfo->guid) {
1879                         str = mono_string_to_utf8 (minfo->guid);
1880                         len = strlen (str);
1881                         sigbuffer_add_value (&buf, len);
1882                         sigbuffer_add_mem (&buf, str, len);
1883                         g_free (str);
1884                 } else {
1885                         sigbuffer_add_value (&buf, 0);
1886                 }
1887                 /* native type name */
1888                 sigbuffer_add_value (&buf, 0);
1889                 /* custom marshaler type name */
1890                 if (minfo->marshaltype || minfo->marshaltyperef) {
1891                         if (minfo->marshaltyperef)
1892                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1893                         else
1894                                 str = mono_string_to_utf8 (minfo->marshaltype);
1895                         len = strlen (str);
1896                         sigbuffer_add_value (&buf, len);
1897                         sigbuffer_add_mem (&buf, str, len);
1898                         g_free (str);
1899                 } else {
1900                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1901                         sigbuffer_add_value (&buf, 0);
1902                 }
1903                 if (minfo->mcookie) {
1904                         str = mono_string_to_utf8 (minfo->mcookie);
1905                         len = strlen (str);
1906                         sigbuffer_add_value (&buf, len);
1907                         sigbuffer_add_mem (&buf, str, len);
1908                         g_free (str);
1909                 } else {
1910                         sigbuffer_add_value (&buf, 0);
1911                 }
1912                 break;
1913         default:
1914                 break;
1915         }
1916         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1917         sigbuffer_free (&buf);
1918         return idx;
1919 }
1920
1921 static void
1922 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1923 {
1924         MonoDynamicTable *table;
1925         guint32 *values;
1926
1927         /* maybe this fixup should be done in the C# code */
1928         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1929                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1930         table = &assembly->tables [MONO_TABLE_FIELD];
1931         fb->table_idx = table->next_idx ++;
1932         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1933         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1934         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1935         values [MONO_FIELD_FLAGS] = fb->attrs;
1936         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1937
1938         if (fb->offset != -1) {
1939                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1940                 table->rows ++;
1941                 alloc_table (table, table->rows);
1942                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1943                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1944                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1945         }
1946         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1947                 guint32 field_type = 0;
1948                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1949                 table->rows ++;
1950                 alloc_table (table, table->rows);
1951                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1952                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1953                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1954                 values [MONO_CONSTANT_TYPE] = field_type;
1955                 values [MONO_CONSTANT_PADDING] = 0;
1956         }
1957         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1958                 guint32 rva_idx;
1959                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1960                 table->rows ++;
1961                 alloc_table (table, table->rows);
1962                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1963                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1964                 /*
1965                  * We store it in the code section because it's simpler for now.
1966                  */
1967                 if (fb->rva_data) {
1968                         if (mono_array_length (fb->rva_data) >= 10)
1969                                 stream_data_align (&assembly->code);
1970                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1971                 } else
1972                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1973                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1974         }
1975         if (fb->marshal_info) {
1976                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1977                 table->rows ++;
1978                 alloc_table (table, table->rows);
1979                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1980                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1981                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1982         }
1983 }
1984
1985 static guint32
1986 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1987 {
1988         SigBuffer buf;
1989         guint32 nparams = 0;
1990         MonoReflectionMethodBuilder *mb = fb->get_method;
1991         MonoReflectionMethodBuilder *smb = fb->set_method;
1992         guint32 idx, i;
1993
1994         if (mb && mb->parameters)
1995                 nparams = mono_array_length (mb->parameters);
1996         if (!mb && smb && smb->parameters)
1997                 nparams = mono_array_length (smb->parameters) - 1;
1998         sigbuffer_init (&buf, 32);
1999         if (fb->call_conv & 0x20)
2000                 sigbuffer_add_byte (&buf, 0x28);
2001         else
2002                 sigbuffer_add_byte (&buf, 0x08);
2003         sigbuffer_add_value (&buf, nparams);
2004         if (mb) {
2005                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2006                 for (i = 0; i < nparams; ++i) {
2007                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2008                         encode_reflection_type (assembly, pt, &buf);
2009                 }
2010         } else if (smb && smb->parameters) {
2011                 /* the property type is the last param */
2012                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2013                 for (i = 0; i < nparams; ++i) {
2014                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2015                         encode_reflection_type (assembly, pt, &buf);
2016                 }
2017         } else {
2018                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2019         }
2020
2021         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2022         sigbuffer_free (&buf);
2023         return idx;
2024 }
2025
2026 static void
2027 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2028 {
2029         MonoDynamicTable *table;
2030         guint32 *values;
2031         guint num_methods = 0;
2032         guint32 semaidx;
2033
2034         /* 
2035          * we need to set things in the following tables:
2036          * PROPERTYMAP (info already filled in _get_type_info ())
2037          * PROPERTY    (rows already preallocated in _get_type_info ())
2038          * METHOD      (method info already done with the generic method code)
2039          * METHODSEMANTICS
2040          * CONSTANT
2041          */
2042         table = &assembly->tables [MONO_TABLE_PROPERTY];
2043         pb->table_idx = table->next_idx ++;
2044         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2045         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2046         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2047         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2048
2049         /* FIXME: we still don't handle 'other' methods */
2050         if (pb->get_method) num_methods ++;
2051         if (pb->set_method) num_methods ++;
2052
2053         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2054         table->rows += num_methods;
2055         alloc_table (table, table->rows);
2056
2057         if (pb->get_method) {
2058                 semaidx = table->next_idx ++;
2059                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2061                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2062                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2063         }
2064         if (pb->set_method) {
2065                 semaidx = table->next_idx ++;
2066                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2067                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2068                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2069                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2070         }
2071         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2072                 guint32 field_type = 0;
2073                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2074                 table->rows ++;
2075                 alloc_table (table, table->rows);
2076                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2077                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2078                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2079                 values [MONO_CONSTANT_TYPE] = field_type;
2080                 values [MONO_CONSTANT_PADDING] = 0;
2081         }
2082 }
2083
2084 static void
2085 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2086 {
2087         MonoDynamicTable *table;
2088         guint32 *values;
2089         guint num_methods = 0;
2090         guint32 semaidx;
2091
2092         /* 
2093          * we need to set things in the following tables:
2094          * EVENTMAP (info already filled in _get_type_info ())
2095          * EVENT    (rows already preallocated in _get_type_info ())
2096          * METHOD      (method info already done with the generic method code)
2097          * METHODSEMANTICS
2098          */
2099         table = &assembly->tables [MONO_TABLE_EVENT];
2100         eb->table_idx = table->next_idx ++;
2101         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2102         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2103         values [MONO_EVENT_FLAGS] = eb->attrs;
2104         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2105
2106         /*
2107          * FIXME: we still don't handle 'other' methods 
2108          */
2109         if (eb->add_method) num_methods ++;
2110         if (eb->remove_method) num_methods ++;
2111         if (eb->raise_method) num_methods ++;
2112
2113         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2114         table->rows += num_methods;
2115         alloc_table (table, table->rows);
2116
2117         if (eb->add_method) {
2118                 semaidx = table->next_idx ++;
2119                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2120                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2121                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2122                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2123         }
2124         if (eb->remove_method) {
2125                 semaidx = table->next_idx ++;
2126                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2127                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2128                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2129                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2130         }
2131         if (eb->raise_method) {
2132                 semaidx = table->next_idx ++;
2133                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2134                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2135                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2136                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2137         }
2138 }
2139
2140 static void
2141 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2142 {
2143         MonoDynamicTable *table;
2144         guint32 num_constraints, i;
2145         guint32 *values;
2146         guint32 table_idx;
2147
2148         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2149         num_constraints = gparam->iface_constraints ?
2150                 mono_array_length (gparam->iface_constraints) : 0;
2151         table->rows += num_constraints;
2152         if (gparam->base_type)
2153                 table->rows++;
2154         alloc_table (table, table->rows);
2155
2156         if (gparam->base_type) {
2157                 table_idx = table->next_idx ++;
2158                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2159
2160                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2161                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2162                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2163         }
2164
2165         for (i = 0; i < num_constraints; i++) {
2166                 MonoReflectionType *constraint = mono_array_get (
2167                         gparam->iface_constraints, gpointer, i);
2168
2169                 table_idx = table->next_idx ++;
2170                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2171
2172                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2173                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2174                         assembly, mono_reflection_type_get_handle (constraint));
2175         }
2176 }
2177
2178 static void
2179 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2180 {
2181         GenericParamTableEntry *entry;
2182
2183         /*
2184          * The GenericParam table must be sorted according to the `owner' field.
2185          * We need to do this sorting prior to writing the GenericParamConstraint
2186          * table, since we have to use the final GenericParam table indices there
2187          * and they must also be sorted.
2188          */
2189
2190         entry = g_new0 (GenericParamTableEntry, 1);
2191         entry->owner = owner;
2192         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2193         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2194         entry->gparam = gparam;
2195         
2196         g_ptr_array_add (assembly->gen_params, entry);
2197 }
2198
2199 static void
2200 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2201 {
2202         MonoDynamicTable *table;
2203         MonoGenericParam *param;
2204         guint32 *values;
2205         guint32 table_idx;
2206
2207         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2208         table_idx = table->next_idx ++;
2209         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2210
2211         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2212
2213         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2214         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2215         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2216         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2217
2218         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2219
2220         encode_constraints (entry->gparam, table_idx, assembly);
2221 }
2222
2223 static guint32
2224 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2225 {
2226         MonoDynamicTable *table;
2227         guint32 token;
2228         guint32 *values;
2229         guint32 cols [MONO_ASSEMBLY_SIZE];
2230         const char *pubkey;
2231         guint32 publen;
2232
2233         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2234                 return token;
2235
2236         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2237                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2238                 token = table->next_idx ++;
2239                 table->rows ++;
2240                 alloc_table (table, table->rows);
2241                 values = table->values + token * MONO_MODULEREF_SIZE;
2242                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2243
2244                 token <<= MONO_RESOLTION_SCOPE_BITS;
2245                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2246                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2247
2248                 return token;
2249         }
2250         
2251         if (image->assembly->dynamic)
2252                 /* FIXME: */
2253                 memset (cols, 0, sizeof (cols));
2254         else {
2255                 /* image->assembly->image is the manifest module */
2256                 image = image->assembly->image;
2257                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2258         }
2259
2260         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2261         token = table->next_idx ++;
2262         table->rows ++;
2263         alloc_table (table, table->rows);
2264         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2265         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2266         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2267         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2268         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2269         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2270         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2271         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2272         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2273
2274         if (strcmp ("", image->assembly->aname.culture)) {
2275                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2276                                 image->assembly->aname.culture);
2277         }
2278
2279         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2280                 guchar pubtoken [9];
2281                 pubtoken [0] = 8;
2282                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2283                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2284         } else {
2285                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2286         }
2287         token <<= MONO_RESOLTION_SCOPE_BITS;
2288         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2289         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2290         return token;
2291 }
2292
2293 static guint32
2294 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2295 {
2296         MonoDynamicTable *table;
2297         guint32 *values;
2298         guint32 token;
2299         SigBuffer buf;
2300
2301         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2302                 return token;
2303
2304         sigbuffer_init (&buf, 32);
2305         switch (type->type) {
2306         case MONO_TYPE_FNPTR:
2307         case MONO_TYPE_PTR:
2308         case MONO_TYPE_SZARRAY:
2309         case MONO_TYPE_ARRAY:
2310         case MONO_TYPE_VAR:
2311         case MONO_TYPE_MVAR:
2312         case MONO_TYPE_GENERICINST:
2313                 encode_type (assembly, type, &buf);
2314                 break;
2315         case MONO_TYPE_CLASS:
2316         case MONO_TYPE_VALUETYPE: {
2317                 MonoClass *k = mono_class_from_mono_type (type);
2318                 if (!k || !k->generic_container) {
2319                         sigbuffer_free (&buf);
2320                         return 0;
2321                 }
2322                 encode_type (assembly, type, &buf);
2323                 break;
2324         }
2325         default:
2326                 sigbuffer_free (&buf);
2327                 return 0;
2328         }
2329
2330         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2331         if (assembly->save) {
2332                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2333                 alloc_table (table, table->rows + 1);
2334                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2335                 values [MONO_TYPESPEC_SIGNATURE] = token;
2336         }
2337         sigbuffer_free (&buf);
2338
2339         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2340         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2341         table->next_idx ++;
2342         return token;
2343 }
2344
2345 static guint32
2346 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2347 {
2348         MonoDynamicTable *table;
2349         guint32 *values;
2350         guint32 token, scope, enclosing;
2351         MonoClass *klass;
2352
2353         /* if the type requires a typespec, we must try that first*/
2354         if (try_typespec && (token = create_typespec (assembly, type)))
2355                 return token;
2356         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2357         if (token)
2358                 return token;
2359         klass = mono_class_from_mono_type (type);
2360         if (!klass)
2361                 klass = mono_class_from_mono_type (type);
2362
2363         /*
2364          * If it's in the same module and not a generic type parameter:
2365          */
2366         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2367                         (type->type != MONO_TYPE_MVAR)) {
2368                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2369                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2370                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2371                 return token;
2372         }
2373
2374         if (klass->nested_in) {
2375                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2376                 /* get the typeref idx of the enclosing type */
2377                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2378                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2379         } else {
2380                 scope = resolution_scope_from_image (assembly, klass->image);
2381         }
2382         table = &assembly->tables [MONO_TABLE_TYPEREF];
2383         if (assembly->save) {
2384                 alloc_table (table, table->rows + 1);
2385                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2386                 values [MONO_TYPEREF_SCOPE] = scope;
2387                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2388                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2389         }
2390         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2391         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2392         table->next_idx ++;
2393         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2394         return token;
2395 }
2396
2397 /*
2398  * Despite the name, we handle also TypeSpec (with the above helper).
2399  */
2400 static guint32
2401 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2402 {
2403         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2404 }
2405
2406 #ifndef DISABLE_REFLECTION_EMIT
2407 static guint32
2408 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2409 {
2410         MonoDynamicTable *table;
2411         guint32 *values;
2412         guint32 token, pclass;
2413
2414         switch (parent & MONO_TYPEDEFORREF_MASK) {
2415         case MONO_TYPEDEFORREF_TYPEREF:
2416                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2417                 break;
2418         case MONO_TYPEDEFORREF_TYPESPEC:
2419                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2420                 break;
2421         case MONO_TYPEDEFORREF_TYPEDEF:
2422                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2423                 break;
2424         default:
2425                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2426                 return 0;
2427         }
2428         /* extract the index */
2429         parent >>= MONO_TYPEDEFORREF_BITS;
2430
2431         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2432
2433         if (assembly->save) {
2434                 alloc_table (table, table->rows + 1);
2435                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2436                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2437                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2438                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2439         }
2440
2441         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2442         table->next_idx ++;
2443
2444         return token;
2445 }
2446
2447 /*
2448  * Insert a memberef row into the metadata: the token that point to the memberref
2449  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2450  * mono_image_get_fieldref_token()).
2451  * The sig param is an index to an already built signature.
2452  */
2453 static guint32
2454 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2455 {
2456         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2457         return mono_image_add_memberef_row (assembly, parent, name, sig);
2458 }
2459
2460
2461 static guint32
2462 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2463 {
2464         guint32 token;
2465         MonoMethodSignature *sig;
2466         
2467         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2468
2469         if (create_typespec) {
2470                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2471                 if (token)
2472                         return token;
2473         } 
2474
2475         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2476         if (token && !create_typespec)
2477                 return token;
2478
2479         g_assert (!method->is_inflated);
2480         if (!token) {
2481                 /*
2482                  * A methodref signature can't contain an unmanaged calling convention.
2483                  */
2484                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2485                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2486                         sig->call_convention = MONO_CALL_DEFAULT;
2487                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2488                         method->name,  method_encode_signature (assembly, sig));
2489                 g_free (sig);
2490                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2491         }
2492
2493         if (create_typespec) {
2494                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2495                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2496                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2497
2498                 if (assembly->save) {
2499                         guint32 *values;
2500
2501                         alloc_table (table, table->rows + 1);
2502                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2503                         values [MONO_METHODSPEC_METHOD] = token;
2504                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2505                 }
2506
2507                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2508                 table->next_idx ++;
2509                 /*methodspec and memberef tokens are diferent, */
2510                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2511                 return token;
2512         }
2513         return token;
2514 }
2515
2516 static guint32
2517 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2518 {
2519         guint32 token, parent, sig;
2520         ReflectionMethodBuilder rmb;
2521         char *name;
2522         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2523         
2524         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2525         if (token)
2526                 return token;
2527
2528         name = mono_string_to_utf8 (method->name);
2529         reflection_methodbuilder_from_method_builder (&rmb, method);
2530
2531         /*
2532          * A methodref signature can't contain an unmanaged calling convention.
2533          * Since some flags are encoded as part of call_conv, we need to check against it.
2534         */
2535         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2536                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2537
2538         sig = method_builder_encode_signature (assembly, &rmb);
2539
2540         if (tb->generic_params)
2541                 parent = create_generic_typespec (assembly, tb);
2542         else
2543                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2544
2545         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2546
2547         g_free (name);
2548         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2549         return token;
2550 }
2551
2552 static guint32
2553 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2554                                      const gchar *name, guint32 sig)
2555 {
2556         MonoDynamicTable *table;
2557         guint32 token;
2558         guint32 *values;
2559         
2560         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2561
2562         if (assembly->save) {
2563                 alloc_table (table, table->rows + 1);
2564                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2565                 values [MONO_MEMBERREF_CLASS] = original;
2566                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2567                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2568         }
2569
2570         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2571         table->next_idx ++;
2572
2573         return token;
2574 }
2575
2576 static guint32
2577 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2578 {
2579         SigBuffer buf;
2580         int i;
2581         guint32 nparams = mono_array_length (mb->generic_params);
2582         guint32 idx;
2583
2584         if (!assembly->save)
2585                 return 0;
2586
2587         sigbuffer_init (&buf, 32);
2588
2589         sigbuffer_add_value (&buf, 0xa);
2590         sigbuffer_add_value (&buf, nparams);
2591
2592         for (i = 0; i < nparams; i++) {
2593                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2594                 sigbuffer_add_value (&buf, i);
2595         }
2596
2597         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2598         sigbuffer_free (&buf);
2599         return idx;
2600 }
2601
2602 static guint32
2603 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2604 {
2605         MonoDynamicTable *table;
2606         guint32 *values;
2607         guint32 token, mtoken = 0;
2608
2609         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2610         if (token)
2611                 return token;
2612
2613         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2614
2615         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2616         switch (mono_metadata_token_table (mtoken)) {
2617         case MONO_TABLE_MEMBERREF:
2618                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2619                 break;
2620         case MONO_TABLE_METHOD:
2621                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2622                 break;
2623         default:
2624                 g_assert_not_reached ();
2625         }
2626
2627         if (assembly->save) {
2628                 alloc_table (table, table->rows + 1);
2629                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2630                 values [MONO_METHODSPEC_METHOD] = mtoken;
2631                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2632         }
2633
2634         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2635         table->next_idx ++;
2636
2637         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2638         return token;
2639 }
2640
2641 static guint32
2642 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2643 {
2644         guint32 token;
2645
2646         if (mb->generic_params && create_methodspec) 
2647                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2648
2649         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2650         if (token)
2651                 return token;
2652
2653         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2654         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2655         return token;
2656 }
2657
2658 static guint32
2659 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2660 {
2661         guint32 token, parent, sig;
2662         ReflectionMethodBuilder rmb;
2663         char *name;
2664         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2665         
2666         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2667         if (token)
2668                 return token;
2669
2670         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2671
2672         if (tb->generic_params)
2673                 parent = create_generic_typespec (assembly, tb);
2674         else
2675                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2676         
2677         name = mono_string_to_utf8 (rmb.name);
2678         sig = method_builder_encode_signature (assembly, &rmb);
2679
2680         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2681
2682         g_free (name);
2683         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2684         return token;
2685 }
2686 #endif
2687
2688 static gboolean
2689 is_field_on_inst (MonoClassField *field)
2690 {
2691         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2692 }
2693
2694 /*
2695  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2696  */
2697 static MonoType*
2698 get_field_on_inst_generic_type (MonoClassField *field)
2699 {
2700         MonoClass *class, *gtd;
2701         MonoDynamicGenericClass *dgclass;
2702         int field_index;
2703
2704         g_assert (is_field_on_inst (field));
2705
2706         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2707
2708         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2709                 field_index = field - dgclass->fields;
2710                 return dgclass->field_generic_types [field_index];              
2711         }
2712
2713         class = field->parent;
2714         gtd = class->generic_class->container_class;
2715
2716         if (field >= class->fields && field - class->fields < class->field.count) {
2717                 field_index = field - class->fields;
2718                 return gtd->fields [field_index].type;
2719         }
2720
2721         g_assert_not_reached ();
2722         return 0;
2723 }
2724
2725 #ifndef DISABLE_REFLECTION_EMIT
2726 static guint32
2727 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2728 {
2729         MonoType *type;
2730         guint32 token;
2731
2732         g_assert (field);
2733         g_assert (field->parent);
2734
2735         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2736         if (token)
2737                 return token;
2738
2739         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2740                 int index = field - field->parent->fields;
2741                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2742         } else {
2743                 if (is_field_on_inst (field))
2744                         type = get_field_on_inst_generic_type (field);
2745                 else
2746                         type = mono_field_get_type (field);
2747         }
2748         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2749                                                                                         mono_field_get_name (field),
2750                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2751         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2752         return token;
2753 }
2754
2755 static guint32
2756 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2757 {
2758         guint32 token;
2759         MonoClass *klass;
2760         MonoGenericClass *gclass;
2761         MonoDynamicGenericClass *dgclass;
2762         MonoType *type;
2763         char *name;
2764
2765         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2766         if (token)
2767                 return token;
2768         if (is_sre_field_builder (mono_object_class (f->fb))) {
2769                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2770                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2771                 klass = mono_class_from_mono_type (type);
2772                 gclass = type->data.generic_class;
2773                 g_assert (gclass->is_dynamic);
2774                 dgclass = (MonoDynamicGenericClass *) gclass;
2775
2776                 name = mono_string_to_utf8 (fb->name);
2777                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2778                                                                                                 field_encode_signature (assembly, fb));
2779                 g_free (name);          
2780         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2781                 guint32 sig;
2782                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2783
2784                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785                 klass = mono_class_from_mono_type (type);
2786
2787                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2788                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2789         } else {
2790                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2791                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2792         }
2793
2794         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2795         return token;
2796 }
2797
2798 static guint32
2799 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2800 {
2801         guint32 sig, token;
2802         MonoClass *klass;
2803         MonoGenericClass *gclass;
2804         MonoType *type;
2805
2806         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2807
2808         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2809         if (token)
2810                 return token;
2811
2812         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2813                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2814                 MonoDynamicGenericClass *dgclass;
2815                 ReflectionMethodBuilder rmb;
2816                 char *name;
2817
2818                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2819                 klass = mono_class_from_mono_type (type);
2820
2821                 gclass = type->data.generic_class;
2822                 g_assert (gclass->is_dynamic);
2823                 dgclass = (MonoDynamicGenericClass *) gclass;
2824
2825                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2826
2827                 name = mono_string_to_utf8 (rmb.name);
2828
2829                 sig = method_builder_encode_signature (assembly, &rmb);
2830
2831                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2832                 g_free (name);
2833         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2834                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2835
2836                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2837                 klass = mono_class_from_mono_type (type);
2838
2839                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2840                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2841         } else {
2842                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2843                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2844         }
2845
2846
2847         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2848         return token;
2849 }
2850
2851 static MonoMethod*
2852 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2853 {
2854         MonoClass *klass;
2855         MonoGenericContext tmp_context;
2856         MonoType **type_argv;
2857         MonoGenericInst *ginst;
2858         MonoMethod *method, *inflated;
2859         int count, i;
2860
2861         init_type_builder_generics ((MonoObject*)m->inst);
2862
2863         method = inflate_method (m->inst, (MonoObject*)m->mb);
2864
2865         klass = method->klass;
2866
2867         if (m->method_args == NULL)
2868                 return method;
2869
2870         if (method->is_inflated)
2871                 method = ((MonoMethodInflated *) method)->declaring;
2872
2873         count = mono_array_length (m->method_args);
2874
2875         type_argv = g_new0 (MonoType *, count);
2876         for (i = 0; i < count; i++) {
2877                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2878                 type_argv [i] = mono_reflection_type_get_handle (garg);
2879         }
2880         ginst = mono_metadata_get_generic_inst (count, type_argv);
2881         g_free (type_argv);
2882
2883         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2884         tmp_context.method_inst = ginst;
2885
2886         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2887         return inflated;
2888 }
2889
2890 static guint32
2891 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2892 {
2893         guint32 sig, token = 0;
2894         MonoType *type;
2895         MonoClass *klass;
2896
2897         if (m->method_args) {
2898                 MonoMethod *inflated;
2899
2900                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2901                 if (create_methodspec)
2902                         token = mono_image_get_methodspec_token (assembly, inflated);
2903                 else
2904                         token = mono_image_get_inflated_method_token (assembly, inflated);
2905                 return token;
2906         }
2907
2908         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2909         if (token)
2910                 return token;
2911
2912         if (is_sre_method_builder (mono_object_class (m->mb))) {
2913                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2914                 MonoGenericClass *gclass;
2915                 ReflectionMethodBuilder rmb;
2916                 char *name;
2917
2918                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2919                 klass = mono_class_from_mono_type (type);
2920                 gclass = type->data.generic_class;
2921                 g_assert (gclass->is_dynamic);
2922
2923                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2924
2925                 name = mono_string_to_utf8 (rmb.name);
2926
2927                 sig = method_builder_encode_signature (assembly, &rmb);
2928
2929                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2930                 g_free (name);          
2931         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2932                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2933
2934                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2935                 klass = mono_class_from_mono_type (type);
2936
2937                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2938                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2939         } else {
2940                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2941                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2942         }
2943
2944         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2945         return token;
2946 }
2947
2948 static guint32
2949 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2950 {
2951         SigBuffer buf;
2952         int i;
2953         guint32 nparams = context->method_inst->type_argc;
2954         guint32 idx;
2955
2956         if (!assembly->save)
2957                 return 0;
2958
2959         sigbuffer_init (&buf, 32);
2960         /*
2961          * FIXME: vararg, explicit_this, differenc call_conv values...
2962          */
2963         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2964         sigbuffer_add_value (&buf, nparams);
2965
2966         for (i = 0; i < nparams; i++)
2967                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2968
2969         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2970         sigbuffer_free (&buf);
2971         return idx;
2972 }
2973
2974 static guint32
2975 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2976 {
2977         MonoDynamicTable *table;
2978         guint32 *values;
2979         guint32 token, mtoken = 0, sig;
2980         MonoMethodInflated *imethod;
2981         MonoMethod *declaring;
2982
2983         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2984
2985         g_assert (method->is_inflated);
2986         imethod = (MonoMethodInflated *) method;
2987         declaring = imethod->declaring;
2988
2989         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2990         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2991
2992         if (!mono_method_signature (declaring)->generic_param_count)
2993                 return mtoken;
2994
2995         switch (mono_metadata_token_table (mtoken)) {
2996         case MONO_TABLE_MEMBERREF:
2997                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2998                 break;
2999         case MONO_TABLE_METHOD:
3000                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3001                 break;
3002         default:
3003                 g_assert_not_reached ();
3004         }
3005
3006         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3007
3008         if (assembly->save) {
3009                 alloc_table (table, table->rows + 1);
3010                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3011                 values [MONO_METHODSPEC_METHOD] = mtoken;
3012                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3013         }
3014
3015         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3016         table->next_idx ++;
3017
3018         return token;
3019 }
3020
3021 static guint32
3022 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3023 {
3024         MonoMethodInflated *imethod;
3025         guint32 token;
3026         
3027         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3028         if (token)
3029                 return token;
3030
3031         g_assert (method->is_inflated);
3032         imethod = (MonoMethodInflated *) method;
3033
3034         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3035                 token = method_encode_methodspec (assembly, method);
3036         } else {
3037                 guint32 sig = method_encode_signature (
3038                         assembly, mono_method_signature (imethod->declaring));
3039                 token = mono_image_get_memberref_token (
3040                         assembly, &method->klass->byval_arg, method->name, sig);
3041         }
3042
3043         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3044         return token;
3045 }
3046
3047 static guint32
3048 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3049 {
3050         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3051         guint32 sig, token;
3052
3053         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3054         token = mono_image_get_memberref_token (
3055                 assembly, &m->klass->byval_arg, m->name, sig);
3056
3057         return token;
3058 }
3059
3060 static guint32
3061 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3062 {
3063         MonoDynamicTable *table;
3064         MonoClass *klass;
3065         MonoType *type;
3066         guint32 *values;
3067         guint32 token;
3068         SigBuffer buf;
3069         int count, i;
3070
3071         /*
3072          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3073          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3074          * Because of this, we must not insert it into the `typeref' hash table.
3075          */
3076         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3077         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3078         if (token)
3079                 return token;
3080
3081         sigbuffer_init (&buf, 32);
3082
3083         g_assert (tb->generic_params);
3084         klass = mono_class_from_mono_type (type);
3085
3086         if (tb->generic_container)
3087                 mono_reflection_create_generic_class (tb);
3088
3089         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3090         g_assert (klass->generic_container);
3091         sigbuffer_add_value (&buf, klass->byval_arg.type);
3092         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3093
3094         count = mono_array_length (tb->generic_params);
3095         sigbuffer_add_value (&buf, count);
3096         for (i = 0; i < count; i++) {
3097                 MonoReflectionGenericParam *gparam;
3098
3099                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3100
3101                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3102         }
3103
3104         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3105
3106         if (assembly->save) {
3107                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3108                 alloc_table (table, table->rows + 1);
3109                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3110                 values [MONO_TYPESPEC_SIGNATURE] = token;
3111         }
3112         sigbuffer_free (&buf);
3113
3114         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3115         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3116         table->next_idx ++;
3117         return token;
3118 }
3119
3120 /*
3121  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3122  */
3123 static MonoType*
3124 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3125 {
3126         int i, count, len, pos;
3127         MonoType *t;
3128
3129         count = 0;
3130         if (modreq)
3131                 count += mono_array_length (modreq);
3132         if (modopt)
3133                 count += mono_array_length (modopt);
3134
3135         if (count == 0)
3136                 return mono_metadata_type_dup (NULL, type);
3137
3138         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3139         t = g_malloc (len);
3140         memcpy (t, type, MONO_SIZEOF_TYPE);
3141
3142         t->num_mods = count;
3143         pos = 0;
3144         if (modreq) {
3145                 for (i = 0; i < mono_array_length (modreq); ++i) {
3146                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3147                         t->modifiers [pos].required = 1;
3148                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3149                         pos ++;
3150                 }
3151         }
3152         if (modopt) {
3153                 for (i = 0; i < mono_array_length (modopt); ++i) {
3154                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3155                         t->modifiers [pos].required = 0;
3156                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3157                         pos ++;
3158                 }
3159         }
3160
3161         return t;
3162 }
3163
3164 static void
3165 init_type_builder_generics (MonoObject *type)
3166 {
3167         MonoReflectionTypeBuilder *tb;
3168
3169         if (!is_sre_type_builder(mono_object_class (type)))
3170                 return;
3171         tb = (MonoReflectionTypeBuilder *)type;
3172
3173         if (tb && tb->generic_container)
3174                 mono_reflection_create_generic_class (tb);
3175 }
3176
3177 static guint32
3178 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3179 {
3180         MonoDynamicTable *table;
3181         MonoClass *klass;
3182         MonoType *custom = NULL, *type;
3183         guint32 *values;
3184         guint32 token, pclass, parent, sig;
3185         gchar *name;
3186
3187         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3188         if (token)
3189                 return token;
3190
3191         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3192         name = mono_string_to_utf8 (fb->name);
3193
3194         /*FIXME this is one more layer of ugliness due how types are created.*/
3195         init_type_builder_generics (fb->type);
3196
3197         /* fb->type does not include the custom modifiers */
3198         /* FIXME: We should do this in one place when a fieldbuilder is created */
3199         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3200         if (fb->modreq || fb->modopt)
3201                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3202
3203         sig = fieldref_encode_signature (assembly, NULL, type);
3204         g_free (custom);
3205
3206         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3207         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3208         
3209         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3210         parent >>= MONO_TYPEDEFORREF_BITS;
3211
3212         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3213
3214         if (assembly->save) {
3215                 alloc_table (table, table->rows + 1);
3216                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3217                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3218                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3219                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3220         }
3221
3222         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3223         table->next_idx ++;
3224         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3225         g_free (name);
3226         return token;
3227 }
3228
3229 static guint32
3230 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3231 {
3232         SigBuffer buf;
3233         guint32 nargs;
3234         guint32 size;
3235         guint32 i, idx;
3236
3237         if (!assembly->save)
3238                 return 0;
3239
3240         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3241         g_assert (helper->type == 2);
3242
3243         if (helper->arguments)
3244                 nargs = mono_array_length (helper->arguments);
3245         else
3246                 nargs = 0;
3247
3248         size = 10 + (nargs * 10);
3249         
3250         sigbuffer_init (&buf, 32);
3251
3252         /* Encode calling convention */
3253         /* Change Any to Standard */
3254         if ((helper->call_conv & 0x03) == 0x03)
3255                 helper->call_conv = 0x01;
3256         /* explicit_this implies has_this */
3257         if (helper->call_conv & 0x40)
3258                 helper->call_conv &= 0x20;
3259
3260         if (helper->call_conv == 0) { /* Unmanaged */
3261                 idx = helper->unmanaged_call_conv - 1;
3262         } else {
3263                 /* Managed */
3264                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3265                 if (helper->call_conv & 0x02) /* varargs */
3266                         idx += 0x05;
3267         }
3268
3269         sigbuffer_add_byte (&buf, idx);
3270         sigbuffer_add_value (&buf, nargs);
3271         encode_reflection_type (assembly, helper->return_type, &buf);
3272         for (i = 0; i < nargs; ++i) {
3273                 MonoArray *modreqs = NULL;
3274                 MonoArray *modopts = NULL;
3275                 MonoReflectionType *pt;
3276
3277                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3278                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3279                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3280                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3281
3282                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3283                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3284                 encode_reflection_type (assembly, pt, &buf);
3285         }
3286         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3287         sigbuffer_free (&buf);
3288
3289         return idx;
3290 }
3291
3292 static guint32 
3293 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3294 {
3295         guint32 idx;
3296         MonoDynamicTable *table;
3297         guint32 *values;
3298
3299         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3300         idx = table->next_idx ++;
3301         table->rows ++;
3302         alloc_table (table, table->rows);
3303         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3304
3305         values [MONO_STAND_ALONE_SIGNATURE] =
3306                 mono_reflection_encode_sighelper (assembly, helper);
3307
3308         return idx;
3309 }
3310
3311 static int
3312 reflection_cc_to_file (int call_conv) {
3313         switch (call_conv & 0x3) {
3314         case 0:
3315         case 1: return MONO_CALL_DEFAULT;
3316         case 2: return MONO_CALL_VARARG;
3317         default:
3318                 g_assert_not_reached ();
3319         }
3320         return 0;
3321 }
3322 #endif /* !DISABLE_REFLECTION_EMIT */
3323
3324 typedef struct {
3325         MonoType *parent;
3326         MonoMethodSignature *sig;
3327         char *name;
3328         guint32 token;
3329 } ArrayMethod;
3330
3331 #ifndef DISABLE_REFLECTION_EMIT
3332 static guint32
3333 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3334 {
3335         guint32 nparams, i;
3336         GList *tmp;
3337         char *name;
3338         MonoMethodSignature *sig;
3339         ArrayMethod *am;
3340         MonoType *mtype;
3341
3342         name = mono_string_to_utf8 (m->name);
3343         nparams = mono_array_length (m->parameters);
3344         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3345         sig->hasthis = 1;
3346         sig->sentinelpos = -1;
3347         sig->call_convention = reflection_cc_to_file (m->call_conv);
3348         sig->param_count = nparams;
3349         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3350         mtype = mono_reflection_type_get_handle (m->parent);
3351         for (i = 0; i < nparams; ++i)
3352                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3353
3354         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3355                 am = tmp->data;
3356                 if (strcmp (name, am->name) == 0 && 
3357                                 mono_metadata_type_equal (am->parent, mtype) &&
3358                                 mono_metadata_signature_equal (am->sig, sig)) {
3359                         g_free (name);
3360                         g_free (sig);
3361                         m->table_idx = am->token & 0xffffff;
3362                         return am->token;
3363                 }
3364         }
3365         am = g_new0 (ArrayMethod, 1);
3366         am->name = name;
3367         am->sig = sig;
3368         am->parent = mtype;
3369         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3370                 method_encode_signature (assembly, sig));
3371         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3372         m->table_idx = am->token & 0xffffff;
3373         return am->token;
3374 }
3375
3376 /*
3377  * Insert into the metadata tables all the info about the TypeBuilder tb.
3378  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3379  */
3380 static void
3381 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3382 {
3383         MonoDynamicTable *table;
3384         guint *values;
3385         int i, is_object = 0, is_system = 0;
3386         char *n;
3387
3388         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3389         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3390         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3391         n = mono_string_to_utf8 (tb->name);
3392         if (strcmp (n, "Object") == 0)
3393                 is_object++;
3394         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3395         g_free (n);
3396         n = mono_string_to_utf8 (tb->nspace);
3397         if (strcmp (n, "System") == 0)
3398                 is_system++;
3399         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3400         g_free (n);
3401         if (tb->parent && !(is_system && is_object) && 
3402                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3403                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3404         } else {
3405                 values [MONO_TYPEDEF_EXTENDS] = 0;
3406         }
3407         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3408         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3409
3410         /*
3411          * if we have explicitlayout or sequentiallayouts, output data in the
3412          * ClassLayout table.
3413          */
3414         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3415                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3416                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3417                 table->rows++;
3418                 alloc_table (table, table->rows);
3419                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3420                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3421                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3422                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3423         }
3424
3425         /* handle interfaces */
3426         if (tb->interfaces) {
3427                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3428                 i = table->rows;
3429                 table->rows += mono_array_length (tb->interfaces);
3430                 alloc_table (table, table->rows);
3431                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3432                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3433                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3434                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3435                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3436                         values += MONO_INTERFACEIMPL_SIZE;
3437                 }
3438         }
3439
3440         /* handle fields */
3441         if (tb->fields) {
3442                 table = &assembly->tables [MONO_TABLE_FIELD];
3443                 table->rows += tb->num_fields;
3444                 alloc_table (table, table->rows);
3445                 for (i = 0; i < tb->num_fields; ++i)
3446                         mono_image_get_field_info (
3447                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3448         }
3449
3450         /* handle constructors */
3451         if (tb->ctors) {
3452                 table = &assembly->tables [MONO_TABLE_METHOD];
3453                 table->rows += mono_array_length (tb->ctors);
3454                 alloc_table (table, table->rows);
3455                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3456                         mono_image_get_ctor_info (domain,
3457                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3458         }
3459
3460         /* handle methods */
3461         if (tb->methods) {
3462                 table = &assembly->tables [MONO_TABLE_METHOD];
3463                 table->rows += tb->num_methods;
3464                 alloc_table (table, table->rows);
3465                 for (i = 0; i < tb->num_methods; ++i)
3466                         mono_image_get_method_info (
3467                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3468         }
3469
3470         /* Do the same with properties etc.. */
3471         if (tb->events && mono_array_length (tb->events)) {
3472                 table = &assembly->tables [MONO_TABLE_EVENT];
3473                 table->rows += mono_array_length (tb->events);
3474                 alloc_table (table, table->rows);
3475                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3476                 table->rows ++;
3477                 alloc_table (table, table->rows);
3478                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3479                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3480                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3481                 for (i = 0; i < mono_array_length (tb->events); ++i)
3482                         mono_image_get_event_info (
3483                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3484         }
3485         if (tb->properties && mono_array_length (tb->properties)) {
3486                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3487                 table->rows += mono_array_length (tb->properties);
3488                 alloc_table (table, table->rows);
3489                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3490                 table->rows ++;
3491                 alloc_table (table, table->rows);
3492                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3493                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3494                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3495                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3496                         mono_image_get_property_info (
3497                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3498         }
3499
3500         /* handle generic parameters */
3501         if (tb->generic_params) {
3502                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3503                 table->rows += mono_array_length (tb->generic_params);
3504                 alloc_table (table, table->rows);
3505                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3506                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3507
3508                         mono_image_get_generic_param_info (
3509                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3510                 }
3511         }
3512
3513         mono_image_add_decl_security (assembly, 
3514                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3515
3516         if (tb->subtypes) {
3517                 MonoDynamicTable *ntable;
3518                 
3519                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3520                 ntable->rows += mono_array_length (tb->subtypes);
3521                 alloc_table (ntable, ntable->rows);
3522                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3523
3524                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3525                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3526
3527                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3528                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3529                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3530                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3531                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3532                                 ntable->next_idx, ntable->rows);*/
3533                         values += MONO_NESTED_CLASS_SIZE;
3534                         ntable->next_idx++;
3535                 }
3536         }
3537 }
3538 #endif
3539
3540 static void
3541 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3542 {
3543         int i;
3544
3545         mono_ptr_array_append (*types, type);
3546
3547         if (!type->subtypes)
3548                 return;
3549
3550         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3551                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3552                 collect_types (types, subtype);
3553         }
3554 }
3555
3556 static gint
3557 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3558 {
3559         if ((*type1)->table_idx < (*type2)->table_idx)
3560                 return -1;
3561         else
3562                 if ((*type1)->table_idx > (*type2)->table_idx)
3563                         return 1;
3564         else
3565                 return 0;
3566 }
3567
3568 static void
3569 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3570         int i;
3571
3572         if (!pinfo)
3573                 return;
3574         for (i = 0; i < mono_array_length (pinfo); ++i) {
3575                 MonoReflectionParamBuilder *pb;
3576                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3577                 if (!pb)
3578                         continue;
3579                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3580         }
3581 }
3582
3583 static void
3584 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3585         int i;
3586         
3587         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3588         if (tb->fields) {
3589                 for (i = 0; i < tb->num_fields; ++i) {
3590                         MonoReflectionFieldBuilder* fb;
3591                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3592                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3593                 }
3594         }
3595         if (tb->events) {
3596                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3597                         MonoReflectionEventBuilder* eb;
3598                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3599                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3600                 }
3601         }
3602         if (tb->properties) {
3603                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3604                         MonoReflectionPropertyBuilder* pb;
3605                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3606                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3607                 }
3608         }
3609         if (tb->ctors) {
3610                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3611                         MonoReflectionCtorBuilder* cb;
3612                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3613                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3614                         params_add_cattrs (assembly, cb->pinfo);
3615                 }
3616         }
3617
3618         if (tb->methods) {
3619                 for (i = 0; i < tb->num_methods; ++i) {
3620                         MonoReflectionMethodBuilder* mb;
3621                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3622                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3623                         params_add_cattrs (assembly, mb->pinfo);
3624                 }
3625         }
3626
3627         if (tb->subtypes) {
3628                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3629                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3630         }
3631 }
3632
3633 static void
3634 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3635 {
3636         int i;
3637         
3638         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3639
3640         if (moduleb->global_methods) {
3641                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3642                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3643                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3644                         params_add_cattrs (assembly, mb->pinfo);
3645                 }
3646         }
3647
3648         if (moduleb->global_fields) {
3649                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3650                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3651                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3652                 }
3653         }
3654         
3655         if (moduleb->types) {
3656                 for (i = 0; i < moduleb->num_types; ++i)
3657                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3658         }
3659 }
3660
3661 static void
3662 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3663 {
3664         MonoDynamicTable *table;
3665         guint32 *values;
3666         char blob_size [6];
3667         guchar hash [20];
3668         char *b = blob_size;
3669         char *dir, *path;
3670
3671         table = &assembly->tables [MONO_TABLE_FILE];
3672         table->rows++;
3673         alloc_table (table, table->rows);
3674         values = table->values + table->next_idx * MONO_FILE_SIZE;
3675         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3676         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3677         if (module->image->dynamic) {
3678                 /* This depends on the fact that the main module is emitted last */
3679                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3680                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3681         } else {
3682                 dir = NULL;
3683                 path = g_strdup (module->image->name);
3684         }
3685         mono_sha1_get_digest_from_file (path, hash);
3686         g_free (dir);
3687         g_free (path);
3688         mono_metadata_encode_value (20, b, &b);
3689         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3690         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3691         table->next_idx ++;
3692 }
3693
3694 static void
3695 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3696 {
3697         MonoDynamicTable *table;
3698         int i;
3699
3700         table = &assembly->tables [MONO_TABLE_MODULE];
3701         mb->table_idx = table->next_idx ++;
3702         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3703         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3704         i /= 16;
3705         ++i;
3706         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3707         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3708         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3709         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3710 }
3711
3712 static guint32
3713 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3714         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3715 {
3716         MonoDynamicTable *table;
3717         guint32 *values;
3718         guint32 visib, res;
3719
3720         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3721         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3722                 return 0;
3723
3724         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3725         table->rows++;
3726         alloc_table (table, table->rows);
3727         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3728
3729         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3730         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3731         if (klass->nested_in)
3732                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3733         else
3734                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3735         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3736         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3737
3738         res = table->next_idx;
3739
3740         table->next_idx ++;
3741
3742         /* Emit nested types */
3743         if (klass->ext && klass->ext->nested_classes) {
3744                 GList *tmp;
3745
3746                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3747                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3748         }
3749
3750         return res;
3751 }
3752
3753 static void
3754 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3755         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3756 {
3757         MonoClass *klass;
3758         guint32 idx, i;
3759
3760         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3761
3762         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3763
3764         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3765                                                                                                    parent_index, assembly);
3766
3767         /* 
3768          * Emit nested types
3769          * We need to do this ourselves since klass->nested_classes is not set up.
3770          */
3771         if (tb->subtypes) {
3772                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3773                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3774         }
3775 }
3776
3777 static void
3778 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3779         guint32 module_index, MonoDynamicImage *assembly)
3780 {
3781         MonoImage *image = module->image;
3782         MonoTableInfo  *t;
3783         guint32 i;
3784
3785         t = &image->tables [MONO_TABLE_TYPEDEF];
3786
3787         for (i = 0; i < t->rows; ++i) {
3788                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3789
3790                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3791                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3792         }
3793 }
3794
3795 static void
3796 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3797 {
3798         MonoDynamicTable *table;
3799         guint32 *values;
3800         guint32 scope, scope_idx, impl, current_idx;
3801         gboolean forwarder = TRUE;
3802         gpointer iter = NULL;
3803         MonoClass *nested;
3804
3805         if (klass->nested_in) {
3806                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3807                 forwarder = FALSE;
3808         } else {
3809                 scope = resolution_scope_from_image (assembly, klass->image);
3810                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3811                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3812                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3813         }
3814
3815         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3816
3817         table->rows++;
3818         alloc_table (table, table->rows);
3819         current_idx = table->next_idx;
3820         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3821
3822         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3823         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3824         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3825         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3826         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3827
3828         table->next_idx++;
3829
3830         while ((nested = mono_class_get_nested_types (klass, &iter)))
3831                 add_exported_type (assemblyb, assembly, nested, current_idx);
3832 }
3833
3834 static void
3835 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3836 {
3837         MonoClass *klass;
3838         int i;
3839
3840         if (!assemblyb->type_forwarders)
3841                 return;
3842
3843         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3844                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3845                 MonoType *type;
3846                 if (!t)
3847                         continue;
3848
3849                 type = mono_reflection_type_get_handle (t);
3850                 g_assert (type);
3851
3852                 klass = mono_class_from_mono_type (type);
3853
3854                 add_exported_type (assemblyb, assembly, klass, 0);
3855         }
3856 }
3857
3858 #define align_pointer(base,p)\
3859         do {\
3860                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3861                 if (__diff & 3)\
3862                         (p) += 4 - (__diff & 3);\
3863         } while (0)
3864
3865 static int
3866 compare_constants (const void *a, const void *b)
3867 {
3868         const guint32 *a_values = a;
3869         const guint32 *b_values = b;
3870         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3871 }
3872
3873 static int
3874 compare_semantics (const void *a, const void *b)
3875 {
3876         const guint32 *a_values = a;
3877         const guint32 *b_values = b;
3878         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3879         if (assoc)
3880                 return assoc;
3881         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3882 }
3883
3884 static int
3885 compare_custom_attrs (const void *a, const void *b)
3886 {
3887         const guint32 *a_values = a;
3888         const guint32 *b_values = b;
3889
3890         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3891 }
3892
3893 static int
3894 compare_field_marshal (const void *a, const void *b)
3895 {
3896         const guint32 *a_values = a;
3897         const guint32 *b_values = b;
3898
3899         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3900 }
3901
3902 static int
3903 compare_nested (const void *a, const void *b)
3904 {
3905         const guint32 *a_values = a;
3906         const guint32 *b_values = b;
3907
3908         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3909 }
3910
3911 static int
3912 compare_genericparam (const void *a, const void *b)
3913 {
3914         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3915         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3916
3917         if ((*b_entry)->owner == (*a_entry)->owner)
3918                 return 
3919                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3920                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3921         else
3922                 return (*a_entry)->owner - (*b_entry)->owner;
3923 }
3924
3925 static int
3926 compare_declsecurity_attrs (const void *a, const void *b)
3927 {
3928         const guint32 *a_values = a;
3929         const guint32 *b_values = b;
3930
3931         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3932 }
3933
3934 static int
3935 compare_interface_impl (const void *a, const void *b)
3936 {
3937         const guint32 *a_values = a;
3938         const guint32 *b_values = b;
3939
3940         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3941         if (klass)
3942                 return klass;
3943
3944         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3945 }
3946
3947 static void
3948 pad_heap (MonoDynamicStream *sh)
3949 {
3950         if (sh->index & 3) {
3951                 int sz = 4 - (sh->index & 3);
3952                 memset (sh->data + sh->index, 0, sz);
3953                 sh->index += sz;
3954         }
3955 }
3956
3957 struct StreamDesc {
3958         const char *name;
3959         MonoDynamicStream *stream;
3960 };
3961
3962 /*
3963  * build_compressed_metadata() fills in the blob of data that represents the 
3964  * raw metadata as it will be saved in the PE file. The five streams are output 
3965  * and the metadata tables are comnpressed from the guint32 array representation, 
3966  * to the compressed on-disk format.
3967  */
3968 static void
3969 build_compressed_metadata (MonoDynamicImage *assembly)
3970 {
3971         MonoDynamicTable *table;
3972         int i;
3973         guint64 valid_mask = 0;
3974         guint64 sorted_mask;
3975         guint32 heapt_size = 0;
3976         guint32 meta_size = 256; /* allow for header and other stuff */
3977         guint32 table_offset;
3978         guint32 ntables = 0;
3979         guint64 *int64val;
3980         guint32 *int32val;
3981         guint16 *int16val;
3982         MonoImage *meta;
3983         unsigned char *p;
3984         struct StreamDesc stream_desc [5];
3985
3986         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3987         for (i = 0; i < assembly->gen_params->len; i++){
3988                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3989                 write_generic_param_entry (assembly, entry);
3990         }
3991
3992         stream_desc [0].name  = "#~";
3993         stream_desc [0].stream = &assembly->tstream;
3994         stream_desc [1].name  = "#Strings";
3995         stream_desc [1].stream = &assembly->sheap;
3996         stream_desc [2].name  = "#US";
3997         stream_desc [2].stream = &assembly->us;
3998         stream_desc [3].name  = "#Blob";
3999         stream_desc [3].stream = &assembly->blob;
4000         stream_desc [4].name  = "#GUID";
4001         stream_desc [4].stream = &assembly->guid;
4002         
4003         /* tables that are sorted */
4004         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4005                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4006                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4007                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4008                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4009                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4010                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4011         
4012         /* Compute table sizes */
4013         /* the MonoImage has already been created in mono_image_basic_init() */
4014         meta = &assembly->image;
4015
4016         /* sizes should be multiple of 4 */
4017         pad_heap (&assembly->blob);
4018         pad_heap (&assembly->guid);
4019         pad_heap (&assembly->sheap);
4020         pad_heap (&assembly->us);
4021
4022         /* Setup the info used by compute_sizes () */
4023         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4024         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4025         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4026
4027         meta_size += assembly->blob.index;
4028         meta_size += assembly->guid.index;
4029         meta_size += assembly->sheap.index;
4030         meta_size += assembly->us.index;
4031
4032         for (i=0; i < MONO_TABLE_NUM; ++i)
4033                 meta->tables [i].rows = assembly->tables [i].rows;
4034         
4035         for (i = 0; i < MONO_TABLE_NUM; i++){
4036                 if (meta->tables [i].rows == 0)
4037                         continue;
4038                 valid_mask |= (guint64)1 << i;
4039                 ntables ++;
4040                 meta->tables [i].row_size = mono_metadata_compute_size (
4041                         meta, i, &meta->tables [i].size_bitfield);
4042                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4043         }
4044         heapt_size += 24; /* #~ header size */
4045         heapt_size += ntables * 4;
4046         /* make multiple of 4 */
4047         heapt_size += 3;
4048         heapt_size &= ~3;
4049         meta_size += heapt_size;
4050         meta->raw_metadata = g_malloc0 (meta_size);
4051         p = (unsigned char*)meta->raw_metadata;
4052         /* the metadata signature */
4053         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4054         /* version numbers and 4 bytes reserved */
4055         int16val = (guint16*)p;
4056         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4057         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4058         p += 8;
4059         /* version string */
4060         int32val = (guint32*)p;
4061         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4062         p += 4;
4063         memcpy (p, meta->version, strlen (meta->version));
4064         p += GUINT32_FROM_LE (*int32val);
4065         align_pointer (meta->raw_metadata, p);
4066         int16val = (guint16*)p;
4067         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4068         *int16val = GUINT16_TO_LE (5); /* number of streams */
4069         p += 4;
4070
4071         /*
4072          * write the stream info.
4073          */
4074         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4075         table_offset += 3; table_offset &= ~3;
4076
4077         assembly->tstream.index = heapt_size;
4078         for (i = 0; i < 5; ++i) {
4079                 int32val = (guint32*)p;
4080                 stream_desc [i].stream->offset = table_offset;
4081                 *int32val++ = GUINT32_TO_LE (table_offset);
4082                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4083                 table_offset += GUINT32_FROM_LE (*int32val);
4084                 table_offset += 3; table_offset &= ~3;
4085                 p += 8;
4086                 strcpy ((char*)p, stream_desc [i].name);
4087                 p += strlen (stream_desc [i].name) + 1;
4088                 align_pointer (meta->raw_metadata, p);
4089         }
4090         /* 
4091          * now copy the data, the table stream header and contents goes first.
4092          */
4093         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4094         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4095         int32val = (guint32*)p;
4096         *int32val = GUINT32_TO_LE (0); /* reserved */
4097         p += 4;
4098
4099         *p++ = 2; /* version */
4100         *p++ = 0;
4101
4102         if (meta->idx_string_wide)
4103                 *p |= 0x01;
4104         if (meta->idx_guid_wide)
4105                 *p |= 0x02;
4106         if (meta->idx_blob_wide)
4107                 *p |= 0x04;
4108         ++p;
4109         *p++ = 1; /* reserved */
4110         int64val = (guint64*)p;
4111         *int64val++ = GUINT64_TO_LE (valid_mask);
4112         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4113         p += 16;
4114         int32val = (guint32*)p;
4115         for (i = 0; i < MONO_TABLE_NUM; i++){
4116                 if (meta->tables [i].rows == 0)
4117                         continue;
4118                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4119         }
4120         p = (unsigned char*)int32val;
4121
4122         /* sort the tables that still need sorting */
4123         table = &assembly->tables [MONO_TABLE_CONSTANT];
4124         if (table->rows)
4125                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4126         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4127         if (table->rows)
4128                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4129         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4130         if (table->rows)
4131                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4132         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4133         if (table->rows)
4134                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4135         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4136         if (table->rows)
4137                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4138         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4139         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4140         if (table->rows)
4141                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4142         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4143         if (table->rows)
4144                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4145
4146         /* compress the tables */
4147         for (i = 0; i < MONO_TABLE_NUM; i++){
4148                 int row, col;
4149                 guint32 *values;
4150                 guint32 bitfield = meta->tables [i].size_bitfield;
4151                 if (!meta->tables [i].rows)
4152                         continue;
4153                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4154                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4155                 meta->tables [i].base = (char*)p;
4156                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4157                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4158                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4159                                 switch (mono_metadata_table_size (bitfield, col)) {
4160                                 case 1:
4161                                         *p++ = values [col];
4162                                         break;
4163                                 case 2:
4164                                         *p++ = values [col] & 0xff;
4165                                         *p++ = (values [col] >> 8) & 0xff;
4166                                         break;
4167                                 case 4:
4168                                         *p++ = values [col] & 0xff;
4169                                         *p++ = (values [col] >> 8) & 0xff;
4170                                         *p++ = (values [col] >> 16) & 0xff;
4171                                         *p++ = (values [col] >> 24) & 0xff;
4172                                         break;
4173                                 default:
4174                                         g_assert_not_reached ();
4175                                 }
4176                         }
4177                 }
4178                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4179         }
4180         
4181         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4182         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4183         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4184         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4185         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4186
4187         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4188 }
4189
4190 /*
4191  * Some tables in metadata need to be sorted according to some criteria, but
4192  * when methods and fields are first created with reflection, they may be assigned a token
4193  * that doesn't correspond to the final token they will get assigned after the sorting.
4194  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4195  * with the reflection objects that represent them. Once all the tables are set up, the 
4196  * reflection objects will contains the correct table index. fixup_method() will fixup the
4197  * tokens for the method with ILGenerator @ilgen.
4198  */
4199 static void
4200 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4201 {
4202         guint32 code_idx = GPOINTER_TO_UINT (value);
4203         MonoReflectionILTokenInfo *iltoken;
4204         MonoReflectionFieldBuilder *field;
4205         MonoReflectionCtorBuilder *ctor;
4206         MonoReflectionMethodBuilder *method;
4207         MonoReflectionTypeBuilder *tb;
4208         MonoReflectionArrayMethod *am;
4209         guint32 i, idx = 0;
4210         unsigned char *target;
4211
4212         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4213                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4214                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4215                 switch (target [3]) {
4216                 case MONO_TABLE_FIELD:
4217                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4218                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4219                                 idx = field->table_idx;
4220                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4221                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4222                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4223                         } else {
4224                                 g_assert_not_reached ();
4225                         }
4226                         break;
4227                 case MONO_TABLE_METHOD:
4228                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4229                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4230                                 idx = method->table_idx;
4231                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4233                                 idx = ctor->table_idx;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4235                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4236                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4237                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4238                         } else {
4239                                 g_assert_not_reached ();
4240                         }
4241                         break;
4242                 case MONO_TABLE_TYPEDEF:
4243                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4244                                 g_assert_not_reached ();
4245                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4246                         idx = tb->table_idx;
4247                         break;
4248                 case MONO_TABLE_MEMBERREF:
4249                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4250                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4251                                 idx = am->table_idx;
4252                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4253                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4254                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4255                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4256                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4257                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4258                                 continue;
4259                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4260                                 continue;
4261                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4262                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4263                                 g_assert (is_field_on_inst (f));
4264                                 continue;
4265                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4266                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4267                                 continue;
4268                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4269                                 continue;
4270                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4273                                 continue;
4274                         } else {
4275                                 g_assert_not_reached ();
4276                         }
4277                         break;
4278                 case MONO_TABLE_METHODSPEC:
4279                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4280                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281                                 g_assert (mono_method_signature (m)->generic_param_count);
4282                                 continue;
4283                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else {
4288                                 g_assert_not_reached ();
4289                         }
4290                         break;
4291                 default:
4292                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4293                 }
4294                 target [0] = idx & 0xff;
4295                 target [1] = (idx >> 8) & 0xff;
4296                 target [2] = (idx >> 16) & 0xff;
4297         }
4298 }
4299
4300 /*
4301  * fixup_cattrs:
4302  *
4303  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4304  * value is not known when the table is emitted.
4305  */
4306 static void
4307 fixup_cattrs (MonoDynamicImage *assembly)
4308 {
4309         MonoDynamicTable *table;
4310         guint32 *values;
4311         guint32 type, i, idx, token;
4312         MonoObject *ctor;
4313
4314         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4315
4316         for (i = 0; i < table->rows; ++i) {
4317                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4318
4319                 type = values [MONO_CUSTOM_ATTR_TYPE];
4320                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4321                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4322                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4323                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4324                         g_assert (ctor);
4325
4326                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4327                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4328                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4329                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4330                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4331                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4332                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4333                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4334                         }
4335                 }
4336         }
4337 }
4338
4339 static void
4340 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4341 {
4342         MonoDynamicTable *table;
4343         guint32 *values;
4344
4345         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4346         table->rows++;
4347         alloc_table (table, table->rows);
4348         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4349         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4350         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4351         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4352         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4353         table->next_idx++;
4354 }
4355
4356 static void
4357 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4358 {
4359         MonoDynamicTable *table;
4360         guint32 *values;
4361         char blob_size [6];
4362         guchar hash [20];
4363         char *b = blob_size;
4364         char *name, *sname;
4365         guint32 idx, offset;
4366
4367         if (rsrc->filename) {
4368                 name = mono_string_to_utf8 (rsrc->filename);
4369                 sname = g_path_get_basename (name);
4370         
4371                 table = &assembly->tables [MONO_TABLE_FILE];
4372                 table->rows++;
4373                 alloc_table (table, table->rows);
4374                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4375                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4376                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4377                 g_free (sname);
4378
4379                 mono_sha1_get_digest_from_file (name, hash);
4380                 mono_metadata_encode_value (20, b, &b);
4381                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4382                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4383                 g_free (name);
4384                 idx = table->next_idx++;
4385                 rsrc->offset = 0;
4386                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4387         } else {
4388                 char sizebuf [4];
4389                 char *data;
4390                 guint len;
4391                 if (rsrc->data) {
4392                         data = mono_array_addr (rsrc->data, char, 0);
4393                         len = mono_array_length (rsrc->data);
4394                 } else {
4395                         data = NULL;
4396                         len = 0;
4397                 }
4398                 offset = len;
4399                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4400                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4401                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4402                 mono_image_add_stream_data (&assembly->resources, data, len);
4403
4404                 if (!mb->is_main)
4405                         /* 
4406                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4407                          * the main module, but that needs to reference the FILE table
4408                          * which isn't emitted yet.
4409                          */
4410                         return;
4411                 else
4412                         idx = 0;
4413         }
4414
4415         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4416 }
4417
4418 static void
4419 set_version_from_string (MonoString *version, guint32 *values)
4420 {
4421         gchar *ver, *p, *str;
4422         guint32 i;
4423         
4424         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4425         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4426         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4427         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4428         if (!version)
4429                 return;
4430         ver = str = mono_string_to_utf8 (version);
4431         for (i = 0; i < 4; ++i) {
4432                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4433                 switch (*p) {
4434                 case '.':
4435                         p++;
4436                         break;
4437                 case '*':
4438                         /* handle Revision and Build */
4439                         p++;
4440                         break;
4441                 }
4442                 ver = p;
4443         }
4444         g_free (str);
4445 }
4446
4447 static guint32
4448 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4449         gsize len;
4450         guint32 token = 0;
4451         char blob_size [6];
4452         char *b = blob_size;
4453
4454         if (!pkey)
4455                 return token;
4456
4457         len = mono_array_length (pkey);
4458         mono_metadata_encode_value (len, b, &b);
4459         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4460         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4461
4462         assembly->public_key = g_malloc (len);
4463         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4464         assembly->public_key_len = len;
4465
4466         /* Special case: check for ECMA key (16 bytes) */
4467         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4468                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4469                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4470         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4471                 /* minimum key size (in 2.0) is 384 bits */
4472                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4473         } else {
4474                 /* FIXME - verifier */
4475                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4476                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4477         }
4478         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4479
4480         return token;
4481 }
4482
4483 static void
4484 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4485 {
4486         MonoDynamicTable *table;
4487         MonoDynamicImage *assembly;
4488         MonoReflectionAssemblyBuilder *assemblyb;
4489         MonoDomain *domain;
4490         guint32 *values;
4491         int i;
4492         guint32 module_index;
4493
4494         assemblyb = moduleb->assemblyb;
4495         assembly = moduleb->dynamic_image;
4496         domain = mono_object_domain (assemblyb);
4497
4498         /* Emit ASSEMBLY table */
4499         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4500         alloc_table (table, 1);
4501         values = table->values + MONO_ASSEMBLY_SIZE;
4502         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4503         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4504         if (assemblyb->culture) {
4505                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4506         } else {
4507                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4508         }
4509         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4510         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4511         set_version_from_string (assemblyb->version, values);
4512
4513         /* Emit FILE + EXPORTED_TYPE table */
4514         module_index = 0;
4515         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4516                 int j;
4517                 MonoReflectionModuleBuilder *file_module = 
4518                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4519                 if (file_module != moduleb) {
4520                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4521                         module_index ++;
4522                         if (file_module->types) {
4523                                 for (j = 0; j < file_module->num_types; ++j) {
4524                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4525                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4526                                 }
4527                         }
4528                 }
4529         }
4530         if (assemblyb->loaded_modules) {
4531                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4532                         MonoReflectionModule *file_module = 
4533                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4534                         mono_image_fill_file_table (domain, file_module, assembly);
4535                         module_index ++;
4536                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4537                 }
4538         }
4539         if (assemblyb->type_forwarders)
4540                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4541
4542         /* Emit MANIFESTRESOURCE table */
4543         module_index = 0;
4544         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4545                 int j;
4546                 MonoReflectionModuleBuilder *file_module = 
4547                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4548                 /* The table for the main module is emitted later */
4549                 if (file_module != moduleb) {
4550                         module_index ++;
4551                         if (file_module->resources) {
4552                                 int len = mono_array_length (file_module->resources);
4553                                 for (j = 0; j < len; ++j) {
4554                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4555                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4556                                 }
4557                         }
4558                 }
4559         }               
4560 }
4561
4562 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4563
4564 /*
4565  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4566  * for the modulebuilder @moduleb.
4567  * At the end of the process, method and field tokens are fixed up and the 
4568  * on-disk compressed metadata representation is created.
4569  */
4570 void
4571 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4572 {
4573         MonoDynamicTable *table;
4574         MonoDynamicImage *assembly;
4575         MonoReflectionAssemblyBuilder *assemblyb;
4576         MonoDomain *domain;
4577         MonoPtrArray types;
4578         guint32 *values;
4579         int i, j;
4580
4581         assemblyb = moduleb->assemblyb;
4582         assembly = moduleb->dynamic_image;
4583         domain = mono_object_domain (assemblyb);
4584
4585         if (assembly->text_rva)
4586                 return;
4587
4588         assembly->text_rva = START_TEXT_RVA;
4589
4590         if (moduleb->is_main) {
4591                 mono_image_emit_manifest (moduleb);
4592         }
4593
4594         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4595         table->rows = 1; /* .<Module> */
4596         table->next_idx++;
4597         alloc_table (table, table->rows);
4598         /*
4599          * Set the first entry.
4600          */
4601         values = table->values + table->columns;
4602         values [MONO_TYPEDEF_FLAGS] = 0;
4603         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4604         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4605         values [MONO_TYPEDEF_EXTENDS] = 0;
4606         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4607         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4608
4609         /* 
4610          * handle global methods 
4611          * FIXME: test what to do when global methods are defined in multiple modules.
4612          */
4613         if (moduleb->global_methods) {
4614                 table = &assembly->tables [MONO_TABLE_METHOD];
4615                 table->rows += mono_array_length (moduleb->global_methods);
4616                 alloc_table (table, table->rows);
4617                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4618                         mono_image_get_method_info (
4619                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4620         }
4621         if (moduleb->global_fields) {
4622                 table = &assembly->tables [MONO_TABLE_FIELD];
4623                 table->rows += mono_array_length (moduleb->global_fields);
4624                 alloc_table (table, table->rows);
4625                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4626                         mono_image_get_field_info (
4627                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4628         }
4629
4630         table = &assembly->tables [MONO_TABLE_MODULE];
4631         alloc_table (table, 1);
4632         mono_image_fill_module_table (domain, moduleb, assembly);
4633
4634         /* Collect all types into a list sorted by their table_idx */
4635         mono_ptr_array_init (types, moduleb->num_types);
4636
4637         if (moduleb->types)
4638                 for (i = 0; i < moduleb->num_types; ++i) {
4639                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4640                         collect_types (&types, type);
4641                 }
4642
4643         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4644         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4645         table->rows += mono_ptr_array_size (types);
4646         alloc_table (table, table->rows);
4647
4648         /*
4649          * Emit type names + namespaces at one place inside the string heap,
4650          * so load_class_names () needs to touch fewer pages.
4651          */
4652         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4653                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4654                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4655         }
4656         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4657                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4658                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4659         }
4660
4661         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4662                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4663                 mono_image_get_type_info (domain, type, assembly);
4664         }
4665
4666         /* 
4667          * table->rows is already set above and in mono_image_fill_module_table.
4668          */
4669         /* add all the custom attributes at the end, once all the indexes are stable */
4670         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4671
4672         /* CAS assembly permissions */
4673         if (assemblyb->permissions_minimum)
4674                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4675         if (assemblyb->permissions_optional)
4676                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4677         if (assemblyb->permissions_refused)
4678                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4679
4680         module_add_cattrs (assembly, moduleb);
4681
4682         /* fixup tokens */
4683         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4684
4685         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4686          * the final tokens and don't need another fixup pass. */
4687
4688         if (moduleb->global_methods) {
4689                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4690                         MonoReflectionMethodBuilder *mb = mono_array_get (
4691                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4692                         mono_image_add_methodimpl (assembly, mb);
4693                 }
4694         }
4695
4696         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4697                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4698                 if (type->methods) {
4699                         for (j = 0; j < type->num_methods; ++j) {
4700                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4701                                         type->methods, MonoReflectionMethodBuilder*, j);
4702
4703                                 mono_image_add_methodimpl (assembly, mb);
4704                         }
4705                 }
4706         }
4707
4708         mono_ptr_array_destroy (types);
4709
4710         fixup_cattrs (assembly);
4711 }
4712
4713 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4714
4715 void
4716 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4717 {
4718         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4719 }
4720
4721 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4722
4723
4724 typedef struct {
4725         guint32 import_lookup_table;
4726         guint32 timestamp;
4727         guint32 forwarder;
4728         guint32 name_rva;
4729         guint32 import_address_table_rva;
4730 } MonoIDT;
4731
4732 typedef struct {
4733         guint32 name_rva;
4734         guint32 flags;
4735 } MonoILT;
4736
4737 #ifndef DISABLE_REFLECTION_EMIT
4738
4739 /*
4740  * mono_image_insert_string:
4741  * @module: module builder object
4742  * @str: a string
4743  *
4744  * Insert @str into the user string stream of @module.
4745  */
4746 guint32
4747 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4748 {
4749         MonoDynamicImage *assembly;
4750         guint32 idx;
4751         char buf [16];
4752         char *b = buf;
4753         
4754         MONO_ARCH_SAVE_REGS;
4755
4756         if (!module->dynamic_image)
4757                 mono_image_module_basic_init (module);
4758
4759         assembly = module->dynamic_image;
4760         
4761         if (assembly->save) {
4762                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4763                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4764 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4765         {
4766                 char *swapped = g_malloc (2 * mono_string_length (str));
4767                 const char *p = (const char*)mono_string_chars (str);
4768
4769                 swap_with_size (swapped, p, 2, mono_string_length (str));
4770                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4771                 g_free (swapped);
4772         }
4773 #else
4774                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4775 #endif
4776                 mono_image_add_stream_data (&assembly->us, "", 1);
4777         } else {
4778                 idx = assembly->us.index ++;
4779         }
4780
4781         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4782
4783         return MONO_TOKEN_STRING | idx;
4784 }
4785
4786 guint32
4787 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4788 {
4789         MonoClass *klass;
4790         guint32 token = 0;
4791         MonoMethodSignature *sig;
4792
4793         klass = obj->vtable->klass;
4794         if (strcmp (klass->name, "MonoMethod") == 0) {
4795                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4796                 MonoMethodSignature *old;
4797                 guint32 sig_token, parent;
4798                 int nargs, i;
4799
4800                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4801
4802                 nargs = mono_array_length (opt_param_types);
4803                 old = mono_method_signature (method);
4804                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4805
4806                 sig->hasthis = old->hasthis;
4807                 sig->explicit_this = old->explicit_this;
4808                 sig->call_convention = old->call_convention;
4809                 sig->generic_param_count = old->generic_param_count;
4810                 sig->param_count = old->param_count + nargs;
4811                 sig->sentinelpos = old->param_count;
4812                 sig->ret = old->ret;
4813
4814                 for (i = 0; i < old->param_count; i++)
4815                         sig->params [i] = old->params [i];
4816
4817                 for (i = 0; i < nargs; i++) {
4818                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4819                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4820                 }
4821
4822                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4823                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4824                 parent >>= MONO_TYPEDEFORREF_BITS;
4825
4826                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4827                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4828
4829                 sig_token = method_encode_signature (assembly, sig);
4830                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4831         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4832                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4833                 ReflectionMethodBuilder rmb;
4834                 guint32 parent, sig_token;
4835                 int nopt_args, nparams, ngparams, i;
4836                 char *name;
4837
4838                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4839                 rmb.opt_types = opt_param_types;
4840                 nopt_args = mono_array_length (opt_param_types);
4841
4842                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4843                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4844                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4845
4846                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4847                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4848                 sig->call_convention = rmb.call_conv;
4849                 sig->generic_param_count = ngparams;
4850                 sig->param_count = nparams + nopt_args;
4851                 sig->sentinelpos = nparams;
4852                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4853
4854                 for (i = 0; i < nparams; i++) {
4855                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4856                         sig->params [i] = mono_reflection_type_get_handle (rt);
4857                 }
4858
4859                 for (i = 0; i < nopt_args; i++) {
4860                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4861                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4862                 }
4863
4864                 sig_token = method_builder_encode_signature (assembly, &rmb);
4865
4866                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4867                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4868
4869                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4870                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4871
4872                 name = mono_string_to_utf8 (rmb.name);
4873                 token = mono_image_get_varargs_method_token (
4874                         assembly, parent, name, sig_token);
4875                 g_free (name);
4876         } else {
4877                 g_error ("requested method token for %s\n", klass->name);
4878         }
4879
4880         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4881         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4882         return token;
4883 }
4884
4885 /*
4886  * mono_image_create_token:
4887  * @assembly: a dynamic assembly
4888  * @obj:
4889  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4890  *
4891  * Get a token to insert in the IL code stream for the given MemberInfo.
4892  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4893  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4894  * entry.
4895  */
4896 guint32
4897 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4898                                                  gboolean create_open_instance, gboolean register_token)
4899 {
4900         MonoClass *klass;
4901         guint32 token = 0;
4902
4903         klass = obj->vtable->klass;
4904
4905         /* Check for user defined reflection objects */
4906         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4907         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4908                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4909
4910         if (strcmp (klass->name, "MethodBuilder") == 0) {
4911                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4912                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4913
4914                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4915                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4916                 else
4917                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4918                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4919         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4920                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4921                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4922
4923                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4924                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4925                 else
4926                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4927                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4928         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4929                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4930                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4931                 if (tb->generic_params) {
4932                         token = mono_image_get_generic_field_token (assembly, fb);
4933                 } else {
4934                         if (tb->module->dynamic_image == assembly) {
4935                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4936                         } else {
4937                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4938                         }
4939                 }
4940         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4941                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4942                 if (create_open_instance && tb->generic_params) {
4943                         MonoType *type;
4944                         init_type_builder_generics (obj);
4945                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4946                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4947                         token = mono_metadata_token_from_dor (token);
4948                 } else if (tb->module->dynamic_image == assembly) {
4949                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4950                 } else {
4951                         MonoType *type;
4952                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4953                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4954                 }
4955         } else if (strcmp (klass->name, "MonoType") == 0) {
4956                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4957                 MonoClass *mc = mono_class_from_mono_type (type);
4958                 token = mono_metadata_token_from_dor (
4959                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4960         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4961                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4962                 token = mono_metadata_token_from_dor (
4963                         mono_image_typedef_or_ref (assembly, type));
4964         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4965                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4966                 token = mono_metadata_token_from_dor (
4967                         mono_image_typedef_or_ref (assembly, type));
4968         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4969                    strcmp (klass->name, "MonoMethod") == 0 ||
4970                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4971                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4972                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4973                 if (m->method->is_inflated) {
4974                         if (create_open_instance)
4975                                 token = mono_image_get_methodspec_token (assembly, m->method);
4976                         else
4977                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4978                 } else if ((m->method->klass->image == &assembly->image) &&
4979                          !m->method->klass->generic_class) {
4980                         static guint32 method_table_idx = 0xffffff;
4981                         if (m->method->klass->wastypebuilder) {
4982                                 /* we use the same token as the one that was assigned
4983                                  * to the Methodbuilder.
4984                                  * FIXME: do the equivalent for Fields.
4985                                  */
4986                                 token = m->method->token;
4987                         } else {
4988                                 /*
4989                                  * Each token should have a unique index, but the indexes are
4990                                  * assigned by managed code, so we don't know about them. An
4991                                  * easy solution is to count backwards...
4992                                  */
4993                                 method_table_idx --;
4994                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4995                         }
4996                 } else {
4997                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4998                 }
4999                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5000         } else if (strcmp (klass->name, "MonoField") == 0) {
5001                 MonoReflectionField *f = (MonoReflectionField *)obj;
5002                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5003                         static guint32 field_table_idx = 0xffffff;
5004                         field_table_idx --;
5005                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5006                 } else {
5007                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5008                 }
5009                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5010         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5011                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5012                 token = mono_image_get_array_token (assembly, m);
5013         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5014                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5015                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5016         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5017                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5018                 token = mono_metadata_token_from_dor (
5019                         mono_image_typedef_or_ref (assembly, type));
5020         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5021                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5022                 token = mono_image_get_field_on_inst_token (assembly, f);
5023         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5024                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5025                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5026         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5027                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5028                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5029         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5030                 MonoReflectionType *type = (MonoReflectionType *)obj;
5031                 token = mono_metadata_token_from_dor (
5032                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5033         } else {
5034                 g_error ("requested token for %s\n", klass->name);
5035         }
5036
5037         if (register_token)
5038                 mono_image_register_token (assembly, token, obj);
5039
5040         return token;
5041 }
5042
5043 /*
5044  * mono_image_register_token:
5045  *
5046  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5047  * the Module.ResolveXXXToken () methods to work.
5048  */
5049 void
5050 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5051 {
5052         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5053         if (prev) {
5054                 /* There could be multiple MethodInfo objects with the same token */
5055                 //g_assert (prev == obj);
5056         } else {
5057                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5058         }
5059 }
5060
5061 static MonoDynamicImage*
5062 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5063 {
5064         static const guchar entrycode [16] = {0xff, 0x25, 0};
5065         MonoDynamicImage *image;
5066         int i;
5067
5068         const char *version;
5069
5070         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5071                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5072         else
5073                 version = mono_get_runtime_info ()->runtime_version;
5074
5075 #if HAVE_BOEHM_GC
5076         /* The MonoGHashTable's need GC tracking */
5077         image = GC_MALLOC (sizeof (MonoDynamicImage));
5078 #else
5079         image = g_new0 (MonoDynamicImage, 1);
5080 #endif
5081         
5082         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5083         
5084         /*g_print ("created image %p\n", image);*/
5085         /* keep in sync with image.c */
5086         image->image.name = assembly_name;
5087         image->image.assembly_name = image->image.name; /* they may be different */
5088         image->image.module_name = module_name;
5089         image->image.version = g_strdup (version);
5090         image->image.md_version_major = 1;
5091         image->image.md_version_minor = 1;
5092         image->image.dynamic = TRUE;
5093
5094         image->image.references = g_new0 (MonoAssembly*, 1);
5095         image->image.references [0] = NULL;
5096
5097         mono_image_init (&image->image);
5098
5099         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5100         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5101         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5102         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5103         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5104         image->handleref = g_hash_table_new (NULL, NULL);
5105         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5106         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5107         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5108         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5109         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5110         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5111         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5112         image->gen_params = g_ptr_array_new ();
5113         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5114
5115         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5116         string_heap_init (&image->sheap);
5117         mono_image_add_stream_data (&image->us, "", 1);
5118         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5119         /* import tables... */
5120         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5121         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5122         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5123         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5124         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5125         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5126         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5127         stream_data_align (&image->code);
5128
5129         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5130
5131         for (i=0; i < MONO_TABLE_NUM; ++i) {
5132                 image->tables [i].next_idx = 1;
5133                 image->tables [i].columns = table_sizes [i];
5134         }
5135
5136         image->image.assembly = (MonoAssembly*)assembly;
5137         image->run = assembly->run;
5138         image->save = assembly->save;
5139         image->pe_kind = 0x1; /* ILOnly */
5140         image->machine = 0x14c; /* I386 */
5141         
5142         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5143
5144         return image;
5145 }
5146 #endif
5147
5148 static void
5149 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5150 {
5151         g_free (key);
5152 }
5153
5154 static void
5155 release_hashtable (MonoGHashTable **hash)
5156 {
5157         if (*hash) {
5158                 mono_g_hash_table_destroy (*hash);
5159                 *hash = NULL;
5160         }
5161 }
5162
5163 void
5164 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5165 {
5166         release_hashtable (&image->token_fixups);
5167         release_hashtable (&image->handleref_managed);
5168         release_hashtable (&image->tokens);
5169         release_hashtable (&image->remapped_tokens);
5170         release_hashtable (&image->generic_def_objects);
5171         release_hashtable (&image->methodspec);
5172 }
5173
5174 void
5175 mono_dynamic_image_free (MonoDynamicImage *image)
5176 {
5177         MonoDynamicImage *di = image;
5178         GList *list;
5179         int i;
5180
5181         if (di->methodspec)
5182                 mono_g_hash_table_destroy (di->methodspec);
5183         if (di->typespec)
5184                 g_hash_table_destroy (di->typespec);
5185         if (di->typeref)
5186                 g_hash_table_destroy (di->typeref);
5187         if (di->handleref)
5188                 g_hash_table_destroy (di->handleref);
5189         if (di->handleref_managed)
5190                 mono_g_hash_table_destroy (di->handleref_managed);
5191         if (di->tokens)
5192                 mono_g_hash_table_destroy (di->tokens);
5193         if (di->remapped_tokens)
5194                 mono_g_hash_table_destroy (di->remapped_tokens);
5195         if (di->generic_def_objects)
5196                 mono_g_hash_table_destroy (di->generic_def_objects);
5197         if (di->blob_cache) {
5198                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5199                 g_hash_table_destroy (di->blob_cache);
5200         }
5201         if (di->standalonesig_cache)
5202                 g_hash_table_destroy (di->standalonesig_cache);
5203         for (list = di->array_methods; list; list = list->next) {
5204                 ArrayMethod *am = (ArrayMethod *)list->data;
5205                 g_free (am->sig);
5206                 g_free (am->name);
5207                 g_free (am);
5208         }
5209         g_list_free (di->array_methods);
5210         if (di->gen_params) {
5211                 for (i = 0; i < di->gen_params->len; i++) {
5212                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5213                         mono_gc_deregister_root ((char*) &entry->gparam);
5214                         g_free (entry);
5215                 }
5216                 g_ptr_array_free (di->gen_params, TRUE);
5217         }
5218         if (di->token_fixups)
5219                 mono_g_hash_table_destroy (di->token_fixups);
5220         if (di->method_to_table_idx)
5221                 g_hash_table_destroy (di->method_to_table_idx);
5222         if (di->field_to_table_idx)
5223                 g_hash_table_destroy (di->field_to_table_idx);
5224         if (di->method_aux_hash)
5225                 g_hash_table_destroy (di->method_aux_hash);
5226         if (di->vararg_aux_hash)
5227                 g_hash_table_destroy (di->vararg_aux_hash);
5228         g_free (di->strong_name);
5229         g_free (di->win32_res);
5230         if (di->public_key)
5231                 g_free (di->public_key);
5232
5233         /*g_print ("string heap destroy for image %p\n", di);*/
5234         mono_dynamic_stream_reset (&di->sheap);
5235         mono_dynamic_stream_reset (&di->code);
5236         mono_dynamic_stream_reset (&di->resources);
5237         mono_dynamic_stream_reset (&di->us);
5238         mono_dynamic_stream_reset (&di->blob);
5239         mono_dynamic_stream_reset (&di->tstream);
5240         mono_dynamic_stream_reset (&di->guid);
5241         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5242                 g_free (di->tables [i].values);
5243         }
5244 }       
5245
5246 #ifndef DISABLE_REFLECTION_EMIT
5247
5248 /*
5249  * mono_image_basic_init:
5250  * @assembly: an assembly builder object
5251  *
5252  * Create the MonoImage that represents the assembly builder and setup some
5253  * of the helper hash table and the basic metadata streams.
5254  */
5255 void
5256 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5257 {
5258         MonoDynamicAssembly *assembly;
5259         MonoDynamicImage *image;
5260         MonoDomain *domain = mono_object_domain (assemblyb);
5261         
5262         MONO_ARCH_SAVE_REGS;
5263
5264         if (assemblyb->dynamic_assembly)
5265                 return;
5266
5267 #if HAVE_BOEHM_GC
5268         /* assembly->assembly.image might be GC allocated */
5269         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5270 #else
5271         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5272 #endif
5273
5274         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5275         
5276         assembly->assembly.ref_count = 1;
5277         assembly->assembly.dynamic = TRUE;
5278         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5279         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5280         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5281         if (assemblyb->culture)
5282                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5283         else
5284                 assembly->assembly.aname.culture = g_strdup ("");
5285
5286         if (assemblyb->version) {
5287                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5288                         char **version = g_strsplit (vstr, ".", 4);
5289                         char **parts = version;
5290                         assembly->assembly.aname.major = atoi (*parts++);
5291                         assembly->assembly.aname.minor = atoi (*parts++);
5292                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5293                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5294
5295                         g_strfreev (version);
5296                         g_free (vstr);
5297         } else {
5298                         assembly->assembly.aname.major = 0;
5299                         assembly->assembly.aname.minor = 0;
5300                         assembly->assembly.aname.build = 0;
5301                         assembly->assembly.aname.revision = 0;
5302         }
5303
5304         assembly->run = assemblyb->access != 2;
5305         assembly->save = assemblyb->access != 1;
5306         assembly->domain = domain;
5307
5308         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5309         image->initial_image = TRUE;
5310         assembly->assembly.aname.name = image->image.name;
5311         assembly->assembly.image = &image->image;
5312         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5313                 /* -1 to correct for the trailing NULL byte */
5314                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5315                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5316                 }
5317                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5318         }
5319
5320         mono_domain_assemblies_lock (domain);
5321         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5322         mono_domain_assemblies_unlock (domain);
5323
5324         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5325         
5326         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5327         
5328         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5329 }
5330
5331 #endif /* !DISABLE_REFLECTION_EMIT */
5332
5333 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5334
5335 static int
5336 calc_section_size (MonoDynamicImage *assembly)
5337 {
5338         int nsections = 0;
5339
5340         /* alignment constraints */
5341         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5342         g_assert ((assembly->code.index % 4) == 0);
5343         assembly->meta_size += 3;
5344         assembly->meta_size &= ~3;
5345         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5346         g_assert ((assembly->resources.index % 4) == 0);
5347
5348         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5349         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5350         nsections++;
5351
5352         if (assembly->win32_res) {
5353                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5354
5355                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5356                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5357                 nsections++;
5358         }
5359
5360         assembly->sections [MONO_SECTION_RELOC].size = 12;
5361         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5362         nsections++;
5363
5364         return nsections;
5365 }
5366
5367 typedef struct {
5368         guint32 id;
5369         guint32 offset;
5370         GSList *children;
5371         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5372 } ResTreeNode;
5373
5374 static int
5375 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5376 {
5377         ResTreeNode *t1 = (ResTreeNode*)a;
5378         ResTreeNode *t2 = (ResTreeNode*)b;
5379
5380         return t1->id - t2->id;
5381 }
5382
5383 /*
5384  * resource_tree_create:
5385  *
5386  *  Organize the resources into a resource tree.
5387  */
5388 static ResTreeNode *
5389 resource_tree_create (MonoArray *win32_resources)
5390 {
5391         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5392         GSList *l;
5393         int i;
5394
5395         tree = g_new0 (ResTreeNode, 1);
5396         
5397         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5398                 MonoReflectionWin32Resource *win32_res =
5399                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5400
5401                 /* Create node */
5402
5403                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5404                 lang_node = g_new0 (ResTreeNode, 1);
5405                 lang_node->id = win32_res->lang_id;
5406                 lang_node->win32_res = win32_res;
5407
5408                 /* Create type node if neccesary */
5409                 type_node = NULL;
5410                 for (l = tree->children; l; l = l->next)
5411                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5412                                 type_node = (ResTreeNode*)l->data;
5413                                 break;
5414                         }
5415
5416                 if (!type_node) {
5417                         type_node = g_new0 (ResTreeNode, 1);
5418                         type_node->id = win32_res->res_type;
5419
5420                         /* 
5421                          * The resource types have to be sorted otherwise
5422                          * Windows Explorer can't display the version information.
5423                          */
5424                         tree->children = g_slist_insert_sorted (tree->children, 
5425                                 type_node, resource_tree_compare_by_id);
5426                 }
5427
5428                 /* Create res node if neccesary */
5429                 res_node = NULL;
5430                 for (l = type_node->children; l; l = l->next)
5431                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5432                                 res_node = (ResTreeNode*)l->data;
5433                                 break;
5434                         }
5435
5436                 if (!res_node) {
5437                         res_node = g_new0 (ResTreeNode, 1);
5438                         res_node->id = win32_res->res_id;
5439                         type_node->children = g_slist_append (type_node->children, res_node);
5440                 }
5441
5442                 res_node->children = g_slist_append (res_node->children, lang_node);
5443         }
5444
5445         return tree;
5446 }
5447
5448 /*
5449  * resource_tree_encode:
5450  * 
5451  *   Encode the resource tree into the format used in the PE file.
5452  */
5453 static void
5454 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5455 {
5456         char *entries;
5457         MonoPEResourceDir dir;
5458         MonoPEResourceDirEntry dir_entry;
5459         MonoPEResourceDataEntry data_entry;
5460         GSList *l;
5461         guint32 res_id_entries;
5462
5463         /*
5464          * For the format of the resource directory, see the article
5465          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5466          * Matt Pietrek
5467          */
5468
5469         memset (&dir, 0, sizeof (dir));
5470         memset (&dir_entry, 0, sizeof (dir_entry));
5471         memset (&data_entry, 0, sizeof (data_entry));
5472
5473         g_assert (sizeof (dir) == 16);
5474         g_assert (sizeof (dir_entry) == 8);
5475         g_assert (sizeof (data_entry) == 16);
5476
5477         node->offset = p - begin;
5478
5479         /* IMAGE_RESOURCE_DIRECTORY */
5480         res_id_entries = g_slist_length (node->children);
5481         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5482
5483         memcpy (p, &dir, sizeof (dir));
5484         p += sizeof (dir);
5485
5486         /* Reserve space for entries */
5487         entries = p;
5488         p += sizeof (dir_entry) * res_id_entries;
5489
5490         /* Write children */
5491         for (l = node->children; l; l = l->next) {
5492                 ResTreeNode *child = (ResTreeNode*)l->data;
5493
5494                 if (child->win32_res) {
5495                         guint32 size;
5496
5497                         child->offset = p - begin;
5498
5499                         /* IMAGE_RESOURCE_DATA_ENTRY */
5500                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5501                         size = mono_array_length (child->win32_res->res_data);
5502                         data_entry.rde_size = GUINT32_TO_LE (size);
5503
5504                         memcpy (p, &data_entry, sizeof (data_entry));
5505                         p += sizeof (data_entry);
5506
5507                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5508                         p += size;
5509                 } else {
5510                         resource_tree_encode (child, begin, p, &p);
5511                 }
5512         }
5513
5514         /* IMAGE_RESOURCE_ENTRY */
5515         for (l = node->children; l; l = l->next) {
5516                 ResTreeNode *child = (ResTreeNode*)l->data;
5517
5518                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5519                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5520
5521                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5522                 entries += sizeof (dir_entry);
5523         }
5524
5525         *endbuf = p;
5526 }
5527
5528 static void
5529 resource_tree_free (ResTreeNode * node)
5530 {
5531         GSList * list;
5532         for (list = node->children; list; list = list->next)
5533                 resource_tree_free ((ResTreeNode*)list->data);
5534         g_slist_free(node->children);
5535         g_free (node);
5536 }
5537
5538 static void
5539 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5540 {
5541         char *buf;
5542         char *p;
5543         guint32 size, i;
5544         MonoReflectionWin32Resource *win32_res;
5545         ResTreeNode *tree;
5546
5547         if (!assemblyb->win32_resources)
5548                 return;
5549
5550         /*
5551          * Resources are stored in a three level tree inside the PE file.
5552          * - level one contains a node for each type of resource
5553          * - level two contains a node for each resource
5554          * - level three contains a node for each instance of a resource for a
5555          *   specific language.
5556          */
5557
5558         tree = resource_tree_create (assemblyb->win32_resources);
5559
5560         /* Estimate the size of the encoded tree */
5561         size = 0;
5562         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5563                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5564                 size += mono_array_length (win32_res->res_data);
5565         }
5566         /* Directory structure */
5567         size += mono_array_length (assemblyb->win32_resources) * 256;
5568         p = buf = g_malloc (size);
5569
5570         resource_tree_encode (tree, p, p, &p);
5571
5572         g_assert (p - buf <= size);
5573
5574         assembly->win32_res = g_malloc (p - buf);
5575         assembly->win32_res_size = p - buf;
5576         memcpy (assembly->win32_res, buf, p - buf);
5577
5578         g_free (buf);
5579         resource_tree_free (tree);
5580 }
5581
5582 static void
5583 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5584 {
5585         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5586         int i;
5587
5588         p += sizeof (MonoPEResourceDir);
5589         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5590                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5591                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5592                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5593                         fixup_resource_directory (res_section, child, rva);
5594                 } else {
5595                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5596                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5597                 }
5598
5599                 p += sizeof (MonoPEResourceDirEntry);
5600         }
5601 }
5602
5603 static void
5604 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5605 {
5606         guint32 dummy;
5607         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5608                 g_error ("WriteFile returned %d\n", GetLastError ());
5609 }
5610
5611 /*
5612  * mono_image_create_pefile:
5613  * @mb: a module builder object
5614  * 
5615  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5616  * assembly->pefile where it can be easily retrieved later in chunks.
5617  */
5618 void
5619 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5620 {
5621         MonoMSDOSHeader *msdos;
5622         MonoDotNetHeader *header;
5623         MonoSectionTable *section;
5624         MonoCLIHeader *cli_header;
5625         guint32 size, image_size, virtual_base, text_offset;
5626         guint32 header_start, section_start, file_offset, virtual_offset;
5627         MonoDynamicImage *assembly;
5628         MonoReflectionAssemblyBuilder *assemblyb;
5629         MonoDynamicStream pefile_stream = {0};
5630         MonoDynamicStream *pefile = &pefile_stream;
5631         int i, nsections;
5632         guint32 *rva, value;
5633         guchar *p;
5634         static const unsigned char msheader[] = {
5635                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5636                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5637                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5638                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5639                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5640                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5641                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5642                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5643         };
5644
5645         assemblyb = mb->assemblyb;
5646
5647         mono_image_basic_init (assemblyb);
5648         assembly = mb->dynamic_image;
5649
5650         assembly->pe_kind = assemblyb->pe_kind;
5651         assembly->machine = assemblyb->machine;
5652         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5653         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5654         
5655         mono_image_build_metadata (mb);
5656
5657         if (mb->is_main && assemblyb->resources) {
5658                 int len = mono_array_length (assemblyb->resources);
5659                 for (i = 0; i < len; ++i)
5660                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5661         }
5662
5663         if (mb->resources) {
5664                 int len = mono_array_length (mb->resources);
5665                 for (i = 0; i < len; ++i)
5666                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5667         }
5668
5669         build_compressed_metadata (assembly);
5670
5671         if (mb->is_main)
5672                 assembly_add_win32_resources (assembly, assemblyb);
5673
5674         nsections = calc_section_size (assembly);
5675         
5676         /* The DOS header and stub */
5677         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5678         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5679
5680         /* the dotnet header */
5681         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5682
5683         /* the section tables */
5684         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5685
5686         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5687         virtual_offset = VIRT_ALIGN;
5688         image_size = 0;
5689
5690         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5691                 if (!assembly->sections [i].size)
5692                         continue;
5693                 /* align offsets */
5694                 file_offset += FILE_ALIGN - 1;
5695                 file_offset &= ~(FILE_ALIGN - 1);
5696                 virtual_offset += VIRT_ALIGN - 1;
5697                 virtual_offset &= ~(VIRT_ALIGN - 1);
5698
5699                 assembly->sections [i].offset = file_offset;
5700                 assembly->sections [i].rva = virtual_offset;
5701
5702                 file_offset += assembly->sections [i].size;
5703                 virtual_offset += assembly->sections [i].size;
5704                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5705         }
5706
5707         file_offset += FILE_ALIGN - 1;
5708         file_offset &= ~(FILE_ALIGN - 1);
5709
5710         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5711
5712         /* back-patch info */
5713         msdos = (MonoMSDOSHeader*)pefile->data;
5714         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5715
5716         header = (MonoDotNetHeader*)(pefile->data + header_start);
5717         header->pesig [0] = 'P';
5718         header->pesig [1] = 'E';
5719         
5720         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5721         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5722         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5723         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5724         if (assemblyb->pekind == 1) {
5725                 /* it's a dll */
5726                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5727         } else {
5728                 /* it's an exe */
5729                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5730         }
5731
5732         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5733
5734         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5735         header->pe.pe_major = 6;
5736         header->pe.pe_minor = 0;
5737         size = assembly->sections [MONO_SECTION_TEXT].size;
5738         size += FILE_ALIGN - 1;
5739         size &= ~(FILE_ALIGN - 1);
5740         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5741         size = assembly->sections [MONO_SECTION_RSRC].size;
5742         size += FILE_ALIGN - 1;
5743         size &= ~(FILE_ALIGN - 1);
5744         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5745         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5746         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5747         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5748         /* pe_rva_entry_point always at the beginning of the text section */
5749         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5750
5751         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5752         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5753         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5754         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5755         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5756         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5757         size = section_start;
5758         size += FILE_ALIGN - 1;
5759         size &= ~(FILE_ALIGN - 1);
5760         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5761         size = image_size;
5762         size += VIRT_ALIGN - 1;
5763         size &= ~(VIRT_ALIGN - 1);
5764         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5765
5766         /*
5767         // Translate the PEFileKind value to the value expected by the Windows loader
5768         */
5769         {
5770                 short kind;
5771
5772                 /*
5773                 // PEFileKinds.Dll == 1
5774                 // PEFileKinds.ConsoleApplication == 2
5775                 // PEFileKinds.WindowApplication == 3
5776                 //
5777                 // need to get:
5778                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5779                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5780                 */
5781                 if (assemblyb->pekind == 3)
5782                         kind = 2;
5783                 else
5784                         kind = 3;
5785                 
5786                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5787         }    
5788         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5789         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5790         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5791         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5792         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5793         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5794
5795         /* fill data directory entries */
5796
5797         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5798         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5799
5800         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5801         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5802
5803         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5804         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5805         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5806         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5807         /* patch entrypoint name */
5808         if (assemblyb->pekind == 1)
5809                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5810         else
5811                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5812         /* patch imported function RVA name */
5813         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5814         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5815
5816         /* the import table */
5817         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5818         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5819         /* patch imported dll RVA name and other entries in the dir */
5820         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5821         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5822         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5823         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5824         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5825         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5826
5827         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5828         value = (assembly->text_rva + assembly->imp_names_offset);
5829         *p++ = (value) & 0xff;
5830         *p++ = (value >> 8) & (0xff);
5831         *p++ = (value >> 16) & (0xff);
5832         *p++ = (value >> 24) & (0xff);
5833
5834         /* the CLI header info */
5835         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5836         cli_header->ch_size = GUINT32_FROM_LE (72);
5837         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5838         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5839         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5840         if (assemblyb->entry_point) {
5841                 guint32 table_idx = 0;
5842                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5843                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5844                         table_idx = methodb->table_idx;
5845                 } else {
5846                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5847                 }
5848                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5849         } else {
5850                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5851         }
5852         /* The embedded managed resources */
5853         text_offset = assembly->text_rva + assembly->code.index;
5854         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5855         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5856         text_offset += assembly->resources.index;
5857         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5858         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5859         text_offset += assembly->meta_size;
5860         if (assembly->strong_name_size) {
5861                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5862                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5863                 text_offset += assembly->strong_name_size;
5864         }
5865
5866         /* write the section tables and section content */
5867         section = (MonoSectionTable*)(pefile->data + section_start);
5868         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5869                 static const char section_names [][7] = {
5870                         ".text", ".rsrc", ".reloc"
5871                 };
5872                 if (!assembly->sections [i].size)
5873                         continue;
5874                 strcpy (section->st_name, section_names [i]);
5875                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5876                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5877                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5878                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5879                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5880                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5881                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5882                 section ++;
5883         }
5884         
5885         checked_write_file (file, pefile->data, pefile->index);
5886         
5887         mono_dynamic_stream_reset (pefile);
5888         
5889         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5890                 if (!assembly->sections [i].size)
5891                         continue;
5892                 
5893                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5894                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5895                 
5896                 switch (i) {
5897                 case MONO_SECTION_TEXT:
5898                         /* patch entry point */
5899                         p = (guchar*)(assembly->code.data + 2);
5900                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5901                         *p++ = (value) & 0xff;
5902                         *p++ = (value >> 8) & 0xff;
5903                         *p++ = (value >> 16) & 0xff;
5904                         *p++ = (value >> 24) & 0xff;
5905                 
5906                         checked_write_file (file, assembly->code.data, assembly->code.index);
5907                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5908                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5909                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5910                                 
5911
5912                         g_free (assembly->image.raw_metadata);
5913                         break;
5914                 case MONO_SECTION_RELOC: {
5915                         struct {
5916                                 guint32 page_rva;
5917                                 guint32 block_size;
5918                                 guint16 type_and_offset;
5919                                 guint16 term;
5920                         } reloc;
5921                         
5922                         g_assert (sizeof (reloc) == 12);
5923                         
5924                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5925                         reloc.block_size = GUINT32_FROM_LE (12);
5926                         
5927                         /* 
5928                          * the entrypoint is always at the start of the text section 
5929                          * 3 is IMAGE_REL_BASED_HIGHLOW
5930                          * 2 is patch_size_rva - text_rva
5931                          */
5932                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5933                         reloc.term = 0;
5934                         
5935                         checked_write_file (file, &reloc, sizeof (reloc));
5936                         
5937                         break;
5938                 }
5939                 case MONO_SECTION_RSRC:
5940                         if (assembly->win32_res) {
5941
5942                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5943                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5944                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5945                         }
5946                         break;
5947                 default:
5948                         g_assert_not_reached ();
5949                 }
5950         }
5951         
5952         /* check that the file is properly padded */
5953         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5954                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5955         if (! SetEndOfFile (file))
5956                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5957         
5958         mono_dynamic_stream_reset (&assembly->code);
5959         mono_dynamic_stream_reset (&assembly->us);
5960         mono_dynamic_stream_reset (&assembly->blob);
5961         mono_dynamic_stream_reset (&assembly->guid);
5962         mono_dynamic_stream_reset (&assembly->sheap);
5963
5964         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5965         g_hash_table_destroy (assembly->blob_cache);
5966         assembly->blob_cache = NULL;
5967 }
5968
5969 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5970
5971 void
5972 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5973 {
5974         g_assert_not_reached ();
5975 }
5976
5977 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5978
5979 #ifndef DISABLE_REFLECTION_EMIT
5980
5981 MonoReflectionModule *
5982 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5983 {
5984         char *name;
5985         MonoImage *image;
5986         MonoImageOpenStatus status;
5987         MonoDynamicAssembly *assembly;
5988         guint32 module_count;
5989         MonoImage **new_modules;
5990         gboolean *new_modules_loaded;
5991         
5992         name = mono_string_to_utf8 (fileName);
5993
5994         image = mono_image_open (name, &status);
5995         if (!image) {
5996                 MonoException *exc;
5997                 if (status == MONO_IMAGE_ERROR_ERRNO)
5998                         exc = mono_get_exception_file_not_found (fileName);
5999                 else
6000                         exc = mono_get_exception_bad_image_format (name);
6001                 g_free (name);
6002                 mono_raise_exception (exc);
6003         }
6004
6005         g_free (name);
6006
6007         assembly = ab->dynamic_assembly;
6008         image->assembly = (MonoAssembly*)assembly;
6009
6010         module_count = image->assembly->image->module_count;
6011         new_modules = g_new0 (MonoImage *, module_count + 1);
6012         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6013
6014         if (image->assembly->image->modules)
6015                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6016         if (image->assembly->image->modules_loaded)
6017                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6018         new_modules [module_count] = image;
6019         new_modules_loaded [module_count] = TRUE;
6020         mono_image_addref (image);
6021
6022         g_free (image->assembly->image->modules);
6023         image->assembly->image->modules = new_modules;
6024         image->assembly->image->modules_loaded = new_modules_loaded;
6025         image->assembly->image->module_count ++;
6026
6027         mono_assembly_load_references (image, &status);
6028         if (status) {
6029                 mono_image_close (image);
6030                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6031         }
6032
6033         return mono_module_get_object (mono_domain_get (), image);
6034 }
6035
6036 #endif /* DISABLE_REFLECTION_EMIT */
6037
6038 /*
6039  * We need to return always the same object for MethodInfo, FieldInfo etc..
6040  * but we need to consider the reflected type.
6041  * type uses a different hash, since it uses custom hash/equal functions.
6042  */
6043
6044 typedef struct {
6045         gpointer item;
6046         MonoClass *refclass;
6047 } ReflectedEntry;
6048
6049 static gboolean
6050 reflected_equal (gconstpointer a, gconstpointer b) {
6051         const ReflectedEntry *ea = a;
6052         const ReflectedEntry *eb = b;
6053
6054         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6055 }
6056
6057 static guint
6058 reflected_hash (gconstpointer a) {
6059         const ReflectedEntry *ea = a;
6060         return mono_aligned_addr_hash (ea->item);
6061 }
6062
6063 #define CHECK_OBJECT(t,p,k)     \
6064         do {    \
6065                 t _obj; \
6066                 ReflectedEntry e;       \
6067                 e.item = (p);   \
6068                 e.refclass = (k);       \
6069                 mono_domain_lock (domain);      \
6070                 if (!domain->refobject_hash)    \
6071                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6072                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6073                         mono_domain_unlock (domain);    \
6074                         return _obj;    \
6075                 }       \
6076         mono_domain_unlock (domain); \
6077         } while (0)
6078
6079 #ifdef HAVE_BOEHM_GC
6080 /* ReflectedEntry doesn't need to be GC tracked */
6081 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6082 #define FREE_REFENTRY(entry) g_free ((entry))
6083 #define REFENTRY_REQUIRES_CLEANUP
6084 #else
6085 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6086 /* FIXME: */
6087 #define FREE_REFENTRY(entry)
6088 #endif
6089
6090 #define CACHE_OBJECT(t,p,o,k)   \
6091         do {    \
6092                 t _obj; \
6093         ReflectedEntry pe; \
6094         pe.item = (p); \
6095         pe.refclass = (k); \
6096         mono_domain_lock (domain); \
6097                 if (!domain->refobject_hash)    \
6098                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6099         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6100         if (!_obj) { \
6101                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6102                     e->item = (p);      \
6103                     e->refclass = (k);  \
6104                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6105             _obj = o; \
6106         } \
6107                 mono_domain_unlock (domain);    \
6108         return _obj; \
6109         } while (0)
6110
6111 static void
6112 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6113 {
6114         mono_domain_lock (domain);
6115         if (domain->refobject_hash) {
6116         ReflectedEntry pe;
6117                 gpointer orig_pe, orig_value;
6118
6119                 pe.item = o;
6120                 pe.refclass = klass;
6121                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6122                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6123                         FREE_REFENTRY (orig_pe);
6124                 }
6125         }
6126         mono_domain_unlock (domain);
6127 }
6128
6129 #ifdef REFENTRY_REQUIRES_CLEANUP
6130 static void
6131 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6132 {
6133         FREE_REFENTRY (key);
6134 }
6135 #endif
6136
6137 void
6138 mono_reflection_cleanup_domain (MonoDomain *domain)
6139 {
6140         if (domain->refobject_hash) {
6141 /*let's avoid scanning the whole hashtable if not needed*/
6142 #ifdef REFENTRY_REQUIRES_CLEANUP
6143                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6144 #endif
6145                 mono_g_hash_table_destroy (domain->refobject_hash);
6146                 domain->refobject_hash = NULL;
6147         }
6148 }
6149
6150 #ifndef DISABLE_REFLECTION_EMIT
6151 static gpointer
6152 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6153 {
6154         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6155 }
6156
6157 static gpointer
6158 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6159 {
6160         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6161 }
6162
6163 void
6164 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6165 {
6166         MonoDynamicImage *image = moduleb->dynamic_image;
6167         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6168         if (!image) {
6169                 MonoError error;
6170                 int module_count;
6171                 MonoImage **new_modules;
6172                 MonoImage *ass;
6173                 char *name, *fqname;
6174                 /*
6175                  * FIXME: we already created an image in mono_image_basic_init (), but
6176                  * we don't know which module it belongs to, since that is only 
6177                  * determined at assembly save time.
6178                  */
6179                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6180                 name = mono_string_to_utf8 (ab->name);
6181                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6182                 if (!mono_error_ok (&error)) {
6183                         g_free (name);
6184                         mono_error_raise_exception (&error);
6185                 }
6186                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6187
6188                 moduleb->module.image = &image->image;
6189                 moduleb->dynamic_image = image;
6190                 register_module (mono_object_domain (moduleb), moduleb, image);
6191
6192                 /* register the module with the assembly */
6193                 ass = ab->dynamic_assembly->assembly.image;
6194                 module_count = ass->module_count;
6195                 new_modules = g_new0 (MonoImage *, module_count + 1);
6196
6197                 if (ass->modules)
6198                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6199                 new_modules [module_count] = &image->image;
6200                 mono_image_addref (&image->image);
6201
6202                 g_free (ass->modules);
6203                 ass->modules = new_modules;
6204                 ass->module_count ++;
6205         }
6206 }
6207
6208 void
6209 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6210 {
6211         MonoDynamicImage *image = moduleb->dynamic_image;
6212
6213         g_assert (type->type);
6214         image->wrappers_type = mono_class_from_mono_type (type->type);
6215 }
6216
6217 #endif
6218
6219 /*
6220  * mono_assembly_get_object:
6221  * @domain: an app domain
6222  * @assembly: an assembly
6223  *
6224  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6225  */
6226 MonoReflectionAssembly*
6227 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6228 {
6229         static MonoClass *assembly_type;
6230         MonoReflectionAssembly *res;
6231         
6232         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6233         if (!assembly_type) {
6234                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6235                 if (class == NULL)
6236                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6237                 g_assert (class);
6238                 assembly_type = class;
6239         }
6240         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6241         res->assembly = assembly;
6242
6243         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6244 }
6245
6246
6247
6248 MonoReflectionModule*   
6249 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6250 {
6251         static MonoClass *module_type;
6252         MonoReflectionModule *res;
6253         char* basename;
6254         
6255         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6256         if (!module_type) {
6257                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6258                 if (class == NULL)
6259                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6260                 g_assert (class);
6261                 module_type = class;
6262         }
6263         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6264
6265         res->image = image;
6266         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6267
6268         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6269         basename = g_path_get_basename (image->name);
6270         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6271         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6272         
6273         g_free (basename);
6274
6275         if (image->assembly->image == image) {
6276                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6277         } else {
6278                 int i;
6279                 res->token = 0;
6280                 if (image->assembly->image->modules) {
6281                         for (i = 0; i < image->assembly->image->module_count; i++) {
6282                                 if (image->assembly->image->modules [i] == image)
6283                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6284                         }
6285                         g_assert (res->token);
6286                 }
6287         }
6288
6289         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6290 }
6291
6292 MonoReflectionModule*   
6293 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6294 {
6295         static MonoClass *module_type;
6296         MonoReflectionModule *res;
6297         MonoTableInfo *table;
6298         guint32 cols [MONO_FILE_SIZE];
6299         const char *name;
6300         guint32 i, name_idx;
6301         const char *val;
6302         
6303         if (!module_type) {
6304                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6305                 if (class == NULL)
6306                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6307                 g_assert (class);
6308                 module_type = class;
6309         }
6310         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6311
6312         table = &image->tables [MONO_TABLE_FILE];
6313         g_assert (table_index < table->rows);
6314         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6315
6316         res->image = NULL;
6317         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6318         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6319
6320         /* Check whenever the row has a corresponding row in the moduleref table */
6321         table = &image->tables [MONO_TABLE_MODULEREF];
6322         for (i = 0; i < table->rows; ++i) {
6323                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6324                 val = mono_metadata_string_heap (image, name_idx);
6325                 if (strcmp (val, name) == 0)
6326                         res->image = image->modules [i];
6327         }
6328
6329         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6330         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6331         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6332         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6333         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6334
6335         return res;
6336 }
6337
6338 static gboolean
6339 verify_safe_for_managed_space (MonoType *type)
6340 {
6341         switch (type->type) {
6342 #ifdef DEBUG_HARDER
6343         case MONO_TYPE_ARRAY:
6344                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6345         case MONO_TYPE_PTR:
6346                 return verify_safe_for_managed_space (type->data.type);
6347         case MONO_TYPE_SZARRAY:
6348                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6349         case MONO_TYPE_GENERICINST: {
6350                 MonoGenericInst *inst = type->data.generic_class->inst;
6351                 int i;
6352                 if (!inst->is_open)
6353                         break;
6354                 for (i = 0; i < inst->type_argc; ++i)
6355                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6356                                 return FALSE;
6357                 break;
6358         }
6359 #endif
6360         case MONO_TYPE_VAR:
6361         case MONO_TYPE_MVAR:
6362                 return TRUE;
6363         }
6364         return TRUE;
6365 }
6366
6367 static MonoType*
6368 mono_type_normalize (MonoType *type)
6369 {
6370         int i;
6371         MonoGenericClass *gclass;
6372         MonoGenericInst *ginst;
6373         MonoClass *gtd;
6374         MonoGenericContainer *gcontainer;
6375         MonoType **argv = NULL;
6376         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6377
6378         if (type->type != MONO_TYPE_GENERICINST)
6379                 return type;
6380
6381         gclass = type->data.generic_class;
6382         ginst = gclass->context.class_inst;
6383         if (!ginst->is_open)
6384                 return type;
6385
6386         gtd = gclass->container_class;
6387         gcontainer = gtd->generic_container;
6388         argv = g_newa (MonoType*, ginst->type_argc);
6389
6390         for (i = 0; i < ginst->type_argc; ++i) {
6391                 MonoType *t = ginst->type_argv [i], *norm;
6392                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6393                         is_denorm_gtd = FALSE;
6394                 norm = mono_type_normalize (t);
6395                 argv [i] = norm;
6396                 if (norm != t)
6397                         requires_rebind = TRUE;
6398         }
6399
6400         if (is_denorm_gtd)
6401                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6402
6403         if (requires_rebind) {
6404                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6405                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6406         }
6407
6408         return type;
6409 }
6410 /*
6411  * mono_type_get_object:
6412  * @domain: an app domain
6413  * @type: a type
6414  *
6415  * Return an System.MonoType object representing the type @type.
6416  */
6417 MonoReflectionType*
6418 mono_type_get_object (MonoDomain *domain, MonoType *type)
6419 {
6420         MonoType *norm_type;
6421         MonoReflectionType *res;
6422         MonoClass *klass = mono_class_from_mono_type (type);
6423
6424         /*we must avoid using @type as it might have come
6425          * from a mono_metadata_type_dup and the caller
6426          * expects that is can be freed.
6427          * Using the right type from 
6428          */
6429         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6430
6431         /* void is very common */
6432         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6433                 return (MonoReflectionType*)domain->typeof_void;
6434
6435         /*
6436          * If the vtable of the given class was already created, we can use
6437          * the MonoType from there and avoid all locking and hash table lookups.
6438          * 
6439          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6440          * that the resulting object is different.   
6441          */
6442         if (type == &klass->byval_arg && !klass->image->dynamic) {
6443                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6444                 if (vtable && vtable->type)
6445                         return vtable->type;
6446         }
6447
6448         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6449         mono_domain_lock (domain);
6450         if (!domain->type_hash)
6451                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6452                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6453         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6454                 mono_domain_unlock (domain);
6455                 mono_loader_unlock ();
6456                 return res;
6457         }
6458
6459         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6460          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6461          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6462          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6463          * artifact of how generics are encoded and should be transparent to managed code so we
6464          * need to weed out this diference when retrieving managed System.Type objects.
6465          */
6466         norm_type = mono_type_normalize (type);
6467         if (norm_type != type) {
6468                 res = mono_type_get_object (domain, norm_type);
6469                 mono_g_hash_table_insert (domain->type_hash, type, res);
6470                 mono_domain_unlock (domain);
6471                 mono_loader_unlock ();
6472                 return res;
6473         }
6474
6475         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6476         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6477                 g_assert (0);
6478
6479         if (!verify_safe_for_managed_space (type)) {
6480                 mono_domain_unlock (domain);
6481                 mono_loader_unlock ();
6482                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6483         }
6484
6485         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6486                 gboolean is_type_done = TRUE;
6487                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6488                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6489                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6490                 */
6491                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6492                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6493
6494                         if (gparam->owner && gparam->owner->is_method) {
6495                                 MonoMethod *method = gparam->owner->owner.method;
6496                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6497                                         is_type_done = FALSE;
6498                         } else if (gparam->owner && !gparam->owner->is_method) {
6499                                 MonoClass *klass = gparam->owner->owner.klass;
6500                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6501                                         is_type_done = FALSE;
6502                         }
6503                 } 
6504
6505                 /* g_assert_not_reached (); */
6506                 /* should this be considered an error condition? */
6507                 if (is_type_done && !type->byref) {
6508                         mono_domain_unlock (domain);
6509                         mono_loader_unlock ();
6510                         return mono_class_get_ref_info (klass);
6511                 }
6512         }
6513         /* This is stored in vtables/JITted code so it has to be pinned */
6514         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6515         res->type = type;
6516         mono_g_hash_table_insert (domain->type_hash, type, res);
6517
6518         if (type->type == MONO_TYPE_VOID)
6519                 domain->typeof_void = (MonoObject*)res;
6520
6521         mono_domain_unlock (domain);
6522         mono_loader_unlock ();
6523         return res;
6524 }
6525
6526 /*
6527  * mono_method_get_object:
6528  * @domain: an app domain
6529  * @method: a method
6530  * @refclass: the reflected type (can be NULL)
6531  *
6532  * Return an System.Reflection.MonoMethod object representing the method @method.
6533  */
6534 MonoReflectionMethod*
6535 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6536 {
6537         /*
6538          * We use the same C representation for methods and constructors, but the type 
6539          * name in C# is different.
6540          */
6541         static MonoClass *System_Reflection_MonoMethod = NULL;
6542         static MonoClass *System_Reflection_MonoCMethod = NULL;
6543         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6544         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6545         MonoClass *klass;
6546         MonoReflectionMethod *ret;
6547
6548         if (method->is_inflated) {
6549                 MonoReflectionGenericMethod *gret;
6550
6551                 refclass = method->klass;
6552                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6553                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6554                         if (!System_Reflection_MonoGenericCMethod)
6555                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6556                         klass = System_Reflection_MonoGenericCMethod;
6557                 } else {
6558                         if (!System_Reflection_MonoGenericMethod)
6559                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6560                         klass = System_Reflection_MonoGenericMethod;
6561                 }
6562                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6563                 gret->method.method = method;
6564                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6565                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6566                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6567         }
6568
6569         if (!refclass)
6570                 refclass = method->klass;
6571
6572         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6573         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6574                 if (!System_Reflection_MonoCMethod)
6575                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6576                 klass = System_Reflection_MonoCMethod;
6577         }
6578         else {
6579                 if (!System_Reflection_MonoMethod)
6580                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6581                 klass = System_Reflection_MonoMethod;
6582         }
6583         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6584         ret->method = method;
6585         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6586         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6587 }
6588
6589 /*
6590  * mono_method_clear_object:
6591  *
6592  *   Clear the cached reflection objects for the dynamic method METHOD.
6593  */
6594 void
6595 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6596 {
6597         MonoClass *klass;
6598         g_assert (method->dynamic);
6599
6600         klass = method->klass;
6601         while (klass) {
6602                 clear_cached_object (domain, method, klass);
6603                 klass = klass->parent;
6604         }
6605         /* Added by mono_param_get_objects () */
6606         clear_cached_object (domain, &(method->signature), NULL);
6607         klass = method->klass;
6608         while (klass) {
6609                 clear_cached_object (domain, &(method->signature), klass);
6610                 klass = klass->parent;
6611         }
6612 }
6613
6614 /*
6615  * mono_field_get_object:
6616  * @domain: an app domain
6617  * @klass: a type
6618  * @field: a field
6619  *
6620  * Return an System.Reflection.MonoField object representing the field @field
6621  * in class @klass.
6622  */
6623 MonoReflectionField*
6624 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6625 {
6626         MonoReflectionField *res;
6627         static MonoClass *monofield_klass;
6628
6629         CHECK_OBJECT (MonoReflectionField *, field, klass);
6630         if (!monofield_klass)
6631                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6632         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6633         res->klass = klass;
6634         res->field = field;
6635         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6636
6637         if (is_field_on_inst (field)) {
6638                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6639                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6640         } else {
6641                 if (field->type)
6642                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6643                 res->attrs = mono_field_get_flags (field);
6644         }
6645         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6646 }
6647
6648 /*
6649  * mono_property_get_object:
6650  * @domain: an app domain
6651  * @klass: a type
6652  * @property: a property
6653  *
6654  * Return an System.Reflection.MonoProperty object representing the property @property
6655  * in class @klass.
6656  */
6657 MonoReflectionProperty*
6658 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6659 {
6660         MonoReflectionProperty *res;
6661         static MonoClass *monoproperty_klass;
6662
6663         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6664         if (!monoproperty_klass)
6665                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6666         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6667         res->klass = klass;
6668         res->property = property;
6669         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6670 }
6671
6672 /*
6673  * mono_event_get_object:
6674  * @domain: an app domain
6675  * @klass: a type
6676  * @event: a event
6677  *
6678  * Return an System.Reflection.MonoEvent object representing the event @event
6679  * in class @klass.
6680  */
6681 MonoReflectionEvent*
6682 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6683 {
6684         MonoReflectionEvent *res;
6685         MonoReflectionMonoEvent *mono_event;
6686         static MonoClass *monoevent_klass;
6687
6688         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6689         if (!monoevent_klass)
6690                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6691         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6692         mono_event->klass = klass;
6693         mono_event->event = event;
6694         res = (MonoReflectionEvent*)mono_event;
6695         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6696 }
6697
6698 /**
6699  * mono_get_reflection_missing_object:
6700  * @domain: Domain where the object lives
6701  *
6702  * Returns the System.Reflection.Missing.Value singleton object
6703  * (of type System.Reflection.Missing).
6704  *
6705  * Used as the value for ParameterInfo.DefaultValue when Optional
6706  * is present
6707  */
6708 static MonoObject *
6709 mono_get_reflection_missing_object (MonoDomain *domain)
6710 {
6711         MonoObject *obj;
6712         static MonoClassField *missing_value_field = NULL;
6713         
6714         if (!missing_value_field) {
6715                 MonoClass *missing_klass;
6716                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6717                 mono_class_init (missing_klass);
6718                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6719                 g_assert (missing_value_field);
6720         }
6721         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6722         g_assert (obj);
6723         return obj;
6724 }
6725
6726 static MonoObject*
6727 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6728 {
6729         if (!*dbnull)
6730                 *dbnull = mono_get_dbnull_object (domain);
6731         return *dbnull;
6732 }
6733
6734 static MonoObject*
6735 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6736 {
6737         if (!*reflection_missing)
6738                 *reflection_missing = mono_get_reflection_missing_object (domain);
6739         return *reflection_missing;
6740 }
6741
6742 /*
6743  * mono_param_get_objects:
6744  * @domain: an app domain
6745  * @method: a method
6746  *
6747  * Return an System.Reflection.ParameterInfo array object representing the parameters
6748  * in the method @method.
6749  */
6750 MonoArray*
6751 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6752 {
6753         static MonoClass *System_Reflection_ParameterInfo;
6754         static MonoClass *System_Reflection_ParameterInfo_array;
6755         MonoError error;
6756         MonoArray *res = NULL;
6757         MonoReflectionMethod *member = NULL;
6758         MonoReflectionParameter *param = NULL;
6759         char **names, **blobs = NULL;
6760         guint32 *types = NULL;
6761         MonoType *type = NULL;
6762         MonoObject *dbnull = NULL;
6763         MonoObject *missing = NULL;
6764         MonoMarshalSpec **mspecs;
6765         MonoMethodSignature *sig;
6766         MonoVTable *pinfo_vtable;
6767         int i;
6768
6769         if (!System_Reflection_ParameterInfo_array) {
6770                 MonoClass *klass;
6771
6772                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6773                 mono_memory_barrier ();
6774                 System_Reflection_ParameterInfo = klass; 
6775         
6776                 klass = mono_array_class_get (klass, 1);
6777                 mono_memory_barrier ();
6778                 System_Reflection_ParameterInfo_array = klass;
6779         }
6780
6781         sig = mono_method_signature_checked (method, &error);
6782         if (!mono_error_ok (&error))
6783                 mono_error_raise_exception (&error);
6784
6785         if (!sig->param_count)
6786                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6787
6788         /* Note: the cache is based on the address of the signature into the method
6789          * since we already cache MethodInfos with the method as keys.
6790          */
6791         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6792
6793         member = mono_method_get_object (domain, method, refclass);
6794         names = g_new (char *, sig->param_count);
6795         mono_method_get_param_names (method, (const char **) names);
6796
6797         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6798         mono_method_get_marshal_info (method, mspecs);
6799
6800         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6801         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6802         for (i = 0; i < sig->param_count; ++i) {
6803                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6804                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6805                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6806                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6807                 param->PositionImpl = i;
6808                 param->AttrsImpl = sig->params [i]->attrs;
6809
6810                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6811                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6812                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6813                         else
6814                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6815                 } else {
6816
6817                         if (!blobs) {
6818                                 blobs = g_new0 (char *, sig->param_count);
6819                                 types = g_new0 (guint32, sig->param_count);
6820                                 get_default_param_value_blobs (method, blobs, types); 
6821                         }
6822
6823                         /* Build MonoType for the type from the Constant Table */
6824                         if (!type)
6825                                 type = g_new0 (MonoType, 1);
6826                         type->type = types [i];
6827                         type->data.klass = NULL;
6828                         if (types [i] == MONO_TYPE_CLASS)
6829                                 type->data.klass = mono_defaults.object_class;
6830                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6831                                 /* For enums, types [i] contains the base type */
6832
6833                                         type->type = MONO_TYPE_VALUETYPE;
6834                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6835                         } else
6836                                 type->data.klass = mono_class_from_mono_type (type);
6837
6838                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6839
6840                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6841                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6842                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6843                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6844                                 else
6845                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6846                         }
6847                         
6848                 }
6849
6850                 if (mspecs [i + 1])
6851                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6852                 
6853                 mono_array_setref (res, i, param);
6854         }
6855         g_free (names);
6856         g_free (blobs);
6857         g_free (types);
6858         g_free (type);
6859
6860         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6861                 if (mspecs [i])
6862                         mono_metadata_free_marshal_spec (mspecs [i]);
6863         g_free (mspecs);
6864         
6865         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6866 }
6867
6868 MonoArray*
6869 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6870 {
6871         return mono_param_get_objects_internal (domain, method, NULL);
6872 }
6873
6874 /*
6875  * mono_method_body_get_object:
6876  * @domain: an app domain
6877  * @method: a method
6878  *
6879  * Return an System.Reflection.MethodBody object representing the method @method.
6880  */
6881 MonoReflectionMethodBody*
6882 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6883 {
6884         static MonoClass *System_Reflection_MethodBody = NULL;
6885         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6886         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6887         MonoReflectionMethodBody *ret;
6888         MonoMethodHeader *header;
6889         MonoImage *image;
6890         guint32 method_rva, local_var_sig_token;
6891     char *ptr;
6892         unsigned char format, flags;
6893         int i;
6894
6895         /* for compatibility with .net */
6896     if (method->dynamic)
6897         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6898
6899         if (!System_Reflection_MethodBody)
6900                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6901         if (!System_Reflection_LocalVariableInfo)
6902                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6903         if (!System_Reflection_ExceptionHandlingClause)
6904                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6905
6906         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6907
6908         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6909                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6910             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6911             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6912                 return NULL;
6913
6914         image = method->klass->image;
6915         header = mono_method_get_header (method);
6916
6917         if (!image->dynamic) {
6918                 /* Obtain local vars signature token */
6919                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6920                 ptr = mono_image_rva_map (image, method_rva);
6921                 flags = *(const unsigned char *) ptr;
6922                 format = flags & METHOD_HEADER_FORMAT_MASK;
6923                 switch (format){
6924                 case METHOD_HEADER_TINY_FORMAT:
6925                         local_var_sig_token = 0;
6926                         break;
6927                 case METHOD_HEADER_FAT_FORMAT:
6928                         ptr += 2;
6929                         ptr += 2;
6930                         ptr += 4;
6931                         local_var_sig_token = read32 (ptr);
6932                         break;
6933                 default:
6934                         g_assert_not_reached ();
6935                 }
6936         } else
6937                 local_var_sig_token = 0; //FIXME
6938
6939         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6940
6941         ret->init_locals = header->init_locals;
6942         ret->max_stack = header->max_stack;
6943         ret->local_var_sig_token = local_var_sig_token;
6944         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6945         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6946
6947         /* Locals */
6948         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6949         for (i = 0; i < header->num_locals; ++i) {
6950                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6951                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6952                 info->is_pinned = header->locals [i]->pinned;
6953                 info->local_index = i;
6954                 mono_array_setref (ret->locals, i, info);
6955         }
6956
6957         /* Exceptions */
6958         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6959         for (i = 0; i < header->num_clauses; ++i) {
6960                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6961                 MonoExceptionClause *clause = &header->clauses [i];
6962
6963                 info->flags = clause->flags;
6964                 info->try_offset = clause->try_offset;
6965                 info->try_length = clause->try_len;
6966                 info->handler_offset = clause->handler_offset;
6967                 info->handler_length = clause->handler_len;
6968                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6969                         info->filter_offset = clause->data.filter_offset;
6970                 else if (clause->data.catch_class)
6971                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6972
6973                 mono_array_setref (ret->clauses, i, info);
6974         }
6975
6976         mono_metadata_free_mh (header);
6977         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6978         return ret;
6979 }
6980
6981 /**
6982  * mono_get_dbnull_object:
6983  * @domain: Domain where the object lives
6984  *
6985  * Returns the System.DBNull.Value singleton object
6986  *
6987  * Used as the value for ParameterInfo.DefaultValue 
6988  */
6989 MonoObject *
6990 mono_get_dbnull_object (MonoDomain *domain)
6991 {
6992         MonoObject *obj;
6993         static MonoClassField *dbnull_value_field = NULL;
6994         
6995         if (!dbnull_value_field) {
6996                 MonoClass *dbnull_klass;
6997                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6998                 mono_class_init (dbnull_klass);
6999                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7000                 g_assert (dbnull_value_field);
7001         }
7002         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7003         g_assert (obj);
7004         return obj;
7005 }
7006
7007 static void
7008 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7009 {
7010         guint32 param_index, i, lastp, crow = 0;
7011         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7012         gint32 idx;
7013
7014         MonoClass *klass = method->klass;
7015         MonoImage *image = klass->image;
7016         MonoMethodSignature *methodsig = mono_method_signature (method);
7017
7018         MonoTableInfo *constt;
7019         MonoTableInfo *methodt;
7020         MonoTableInfo *paramt;
7021
7022         if (!methodsig->param_count)
7023                 return;
7024
7025         mono_class_init (klass);
7026
7027         if (klass->image->dynamic) {
7028                 MonoReflectionMethodAux *aux;
7029                 if (method->is_inflated)
7030                         method = ((MonoMethodInflated*)method)->declaring;
7031                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7032                 if (aux && aux->param_defaults) {
7033                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7034                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7035                 }
7036                 return;
7037         }
7038
7039         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7040         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7041         constt = &image->tables [MONO_TABLE_CONSTANT];
7042
7043         idx = mono_method_get_index (method) - 1;
7044         g_assert (idx != -1);
7045
7046         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7047         if (idx + 1 < methodt->rows)
7048                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7049         else
7050                 lastp = paramt->rows + 1;
7051
7052         for (i = param_index; i < lastp; ++i) {
7053                 guint32 paramseq;
7054
7055                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7056                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7057
7058                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7059                         continue;
7060
7061                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7062                 if (!crow) {
7063                         continue;
7064                 }
7065         
7066                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7067                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7068                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7069         }
7070
7071         return;
7072 }
7073
7074 MonoObject *
7075 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7076 {
7077         void *retval;
7078         MonoClass *klass;
7079         MonoObject *object;
7080         MonoType *basetype = type;
7081
7082         if (!blob)
7083                 return NULL;
7084         
7085         klass = mono_class_from_mono_type (type);
7086         if (klass->valuetype) {
7087                 object = mono_object_new (domain, klass);
7088                 retval = ((gchar *) object + sizeof (MonoObject));
7089                 if (klass->enumtype)
7090                         basetype = mono_class_enum_basetype (klass);
7091         } else {
7092                 retval = &object;
7093         }
7094                         
7095         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7096                 return object;
7097         else
7098                 return NULL;
7099 }
7100
7101 static int
7102 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7103         int found_sep;
7104         char *s;
7105         gboolean quoted = FALSE;
7106
7107         memset (assembly, 0, sizeof (MonoAssemblyName));
7108         assembly->culture = "";
7109         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7110
7111         if (*p == '"') {
7112                 quoted = TRUE;
7113                 p++;
7114         }
7115         assembly->name = p;
7116         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7117                 p++;
7118         if (quoted) {
7119                 if (*p != '"')
7120                         return 1;
7121                 *p = 0;
7122                 p++;
7123         }
7124         if (*p != ',')
7125                 return 1;
7126         *p = 0;
7127         /* Remove trailing whitespace */
7128         s = p - 1;
7129         while (*s && g_ascii_isspace (*s))
7130                 *s-- = 0;
7131         p ++;
7132         while (g_ascii_isspace (*p))
7133                 p++;
7134         while (*p) {
7135                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7136                         p += 8;
7137                         assembly->major = strtoul (p, &s, 10);
7138                         if (s == p || *s != '.')
7139                                 return 1;
7140                         p = ++s;
7141                         assembly->minor = strtoul (p, &s, 10);
7142                         if (s == p || *s != '.')
7143                                 return 1;
7144                         p = ++s;
7145                         assembly->build = strtoul (p, &s, 10);
7146                         if (s == p || *s != '.')
7147                                 return 1;
7148                         p = ++s;
7149                         assembly->revision = strtoul (p, &s, 10);
7150                         if (s == p)
7151                                 return 1;
7152                         p = s;
7153                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7154                         p += 8;
7155                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7156                                 assembly->culture = "";
7157                                 p += 7;
7158                         } else {
7159                                 assembly->culture = p;
7160                                 while (*p && *p != ',') {
7161                                         p++;
7162                                 }
7163                         }
7164                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7165                         p += 15;
7166                         if (strncmp (p, "null", 4) == 0) {
7167                                 p += 4;
7168                         } else {
7169                                 int len;
7170                                 gchar *start = p;
7171                                 while (*p && *p != ',') {
7172                                         p++;
7173                                 }
7174                                 len = (p - start + 1);
7175                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7176                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7177                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7178                         }
7179                 } else {
7180                         while (*p && *p != ',')
7181                                 p++;
7182                 }
7183                 found_sep = 0;
7184                 while (g_ascii_isspace (*p) || *p == ',') {
7185                         *p++ = 0;
7186                         found_sep = 1;
7187                         continue;
7188                 }
7189                 /* failed */
7190                 if (!found_sep)
7191                         return 1;
7192         }
7193
7194         return 0;
7195 }
7196
7197 /*
7198  * mono_reflection_parse_type:
7199  * @name: type name
7200  *
7201  * Parse a type name as accepted by the GetType () method and output the info
7202  * extracted in the info structure.
7203  * the name param will be mangled, so, make a copy before passing it to this function.
7204  * The fields in info will be valid until the memory pointed to by name is valid.
7205  *
7206  * See also mono_type_get_name () below.
7207  *
7208  * Returns: 0 on parse error.
7209  */
7210 static int
7211 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7212                              MonoTypeNameParse *info)
7213 {
7214         char *start, *p, *w, *temp, *last_point, *startn;
7215         int in_modifiers = 0;
7216         int isbyref = 0, rank, arity = 0, i;
7217
7218         start = p = w = name;
7219
7220         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7221         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7222         info->name = info->name_space = NULL;
7223         info->nested = NULL;
7224         info->modifiers = NULL;
7225         info->type_arguments = NULL;
7226
7227         /* last_point separates the namespace from the name */
7228         last_point = NULL;
7229         /* Skips spaces */
7230         while (*p == ' ') p++, start++, w++, name++;
7231
7232         while (*p) {
7233                 switch (*p) {
7234                 case '+':
7235                         *p = 0; /* NULL terminate the name */
7236                         startn = p + 1;
7237                         info->nested = g_list_append (info->nested, startn);
7238                         /* we have parsed the nesting namespace + name */
7239                         if (info->name)
7240                                 break;
7241                         if (last_point) {
7242                                 info->name_space = start;
7243                                 *last_point = 0;
7244                                 info->name = last_point + 1;
7245                         } else {
7246                                 info->name_space = (char *)"";
7247                                 info->name = start;
7248                         }
7249                         break;
7250                 case '.':
7251                         last_point = p;
7252                         break;
7253                 case '\\':
7254                         ++p;
7255                         break;
7256                 case '&':
7257                 case '*':
7258                 case '[':
7259                 case ',':
7260                 case ']':
7261                         in_modifiers = 1;
7262                         break;
7263                 case '`':
7264                         ++p;
7265                         i = strtol (p, &temp, 10);
7266                         arity += i;
7267                         if (p == temp)
7268                                 return 0;
7269                         p = temp-1;
7270                         break;
7271                 default:
7272                         break;
7273                 }
7274                 if (in_modifiers)
7275                         break;
7276                 // *w++ = *p++;
7277                 p++;
7278         }
7279         
7280         if (!info->name) {
7281                 if (last_point) {
7282                         info->name_space = start;
7283                         *last_point = 0;
7284                         info->name = last_point + 1;
7285                 } else {
7286                         info->name_space = (char *)"";
7287                         info->name = start;
7288                 }
7289         }
7290         while (*p) {
7291                 switch (*p) {
7292                 case '&':
7293                         if (isbyref) /* only one level allowed by the spec */
7294                                 return 0;
7295                         isbyref = 1;
7296                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7297                         *p++ = 0;
7298                         break;
7299                 case '*':
7300                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7301                         *p++ = 0;
7302                         break;
7303                 case '[':
7304                         if (arity != 0) {
7305                                 *p++ = 0;
7306                                 info->type_arguments = g_ptr_array_new ();
7307                                 for (i = 0; i < arity; i++) {
7308                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7309                                         gboolean fqname = FALSE;
7310
7311                                         g_ptr_array_add (info->type_arguments, subinfo);
7312
7313                                         if (*p == '[') {
7314                                                 p++;
7315                                                 fqname = TRUE;
7316                                         }
7317
7318                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7319                                                 return 0;
7320
7321                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7322                                         if (fqname && (*p != ']')) {
7323                                                 char *aname;
7324
7325                                                 if (*p != ',')
7326                                                         return 0;
7327                                                 *p++ = 0;
7328
7329                                                 aname = p;
7330                                                 while (*p && (*p != ']'))
7331                                                         p++;
7332
7333                                                 if (*p != ']')
7334                                                         return 0;
7335
7336                                                 *p++ = 0;
7337                                                 while (*aname) {
7338                                                         if (g_ascii_isspace (*aname)) {
7339                                                                 ++aname;
7340                                                                 continue;
7341                                                         }
7342                                                         break;
7343                                                 }
7344                                                 if (!*aname ||
7345                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7346                                                         return 0;
7347                                         } else if (fqname && (*p == ']')) {
7348                                                 *p++ = 0;
7349                                         }
7350
7351                                         if (i + 1 < arity) {
7352                                                 if (*p != ',')
7353                                                         return 0;
7354                                         } else {
7355                                                 if (*p != ']')
7356                                                         return 0;
7357                                         }
7358                                         *p++ = 0;
7359                                 }
7360
7361                                 arity = 0;
7362                                 break;
7363                         }
7364                         rank = 1;
7365                         *p++ = 0;
7366                         while (*p) {
7367                                 if (*p == ']')
7368                                         break;
7369                                 if (*p == ',')
7370                                         rank++;
7371                                 else if (*p == '*') /* '*' means unknown lower bound */
7372                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7373                                 else
7374                                         return 0;
7375                                 ++p;
7376                         }
7377                         if (*p++ != ']')
7378                                 return 0;
7379                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7380                         break;
7381                 case ']':
7382                         if (is_recursed)
7383                                 goto end;
7384                         return 0;
7385                 case ',':
7386                         if (is_recursed)
7387                                 goto end;
7388                         *p++ = 0;
7389                         while (*p) {
7390                                 if (g_ascii_isspace (*p)) {
7391                                         ++p;
7392                                         continue;
7393                                 }
7394                                 break;
7395                         }
7396                         if (!*p)
7397                                 return 0; /* missing assembly name */
7398                         if (!assembly_name_to_aname (&info->assembly, p))
7399                                 return 0;
7400                         break;
7401                 default:
7402                         return 0;
7403                 }
7404                 if (info->assembly.name)
7405                         break;
7406         }
7407         // *w = 0; /* terminate class name */
7408  end:
7409         if (!info->name || !*info->name)
7410                 return 0;
7411         if (endptr)
7412                 *endptr = p;
7413         /* add other consistency checks */
7414         return 1;
7415 }
7416
7417 int
7418 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7419 {
7420         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7421 }
7422
7423 static MonoType*
7424 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7425 {
7426         gboolean type_resolve = FALSE;
7427         MonoType *type;
7428         MonoImage *rootimage = image;
7429
7430         if (info->assembly.name) {
7431                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7432                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7433                         /* 
7434                          * This could happen in the AOT compiler case when the search hook is not
7435                          * installed.
7436                          */
7437                         assembly = image->assembly;
7438                 if (!assembly) {
7439                         /* then we must load the assembly ourselve - see #60439 */
7440                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7441                         if (!assembly)
7442                                 return NULL;
7443                 }
7444                 image = assembly->image;
7445         } else if (!image) {
7446                 image = mono_defaults.corlib;
7447         }
7448
7449         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7450         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7451                 image = mono_defaults.corlib;
7452                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7453         }
7454
7455         return type;
7456 }
7457
7458 static MonoType*
7459 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7460 {
7461         MonoClass *klass;
7462         GList *mod;
7463         int modval;
7464         gboolean bounded = FALSE;
7465         
7466         if (!image)
7467                 image = mono_defaults.corlib;
7468
7469         if (ignorecase)
7470                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7471         else
7472                 klass = mono_class_from_name (image, info->name_space, info->name);
7473         if (!klass)
7474                 return NULL;
7475         for (mod = info->nested; mod; mod = mod->next) {
7476                 gpointer iter = NULL;
7477                 MonoClass *parent;
7478
7479                 parent = klass;
7480                 mono_class_init (parent);
7481
7482                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7483                         if (ignorecase) {
7484                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7485                                         break;
7486                         } else {
7487                                 if (strcmp (klass->name, mod->data) == 0)
7488                                         break;
7489                         }
7490                 }
7491                 if (!klass)
7492                         break;
7493         }
7494         if (!klass)
7495                 return NULL;
7496
7497         if (info->type_arguments) {
7498                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7499                 MonoReflectionType *the_type;
7500                 MonoType *instance;
7501                 int i;
7502
7503                 for (i = 0; i < info->type_arguments->len; i++) {
7504                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7505
7506                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7507                         if (!type_args [i]) {
7508                                 g_free (type_args);
7509                                 return NULL;
7510                         }
7511                 }
7512
7513                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7514
7515                 instance = mono_reflection_bind_generic_parameters (
7516                         the_type, info->type_arguments->len, type_args);
7517
7518                 g_free (type_args);
7519                 if (!instance)
7520                         return NULL;
7521
7522                 klass = mono_class_from_mono_type (instance);
7523         }
7524
7525         for (mod = info->modifiers; mod; mod = mod->next) {
7526                 modval = GPOINTER_TO_UINT (mod->data);
7527                 if (!modval) { /* byref: must be last modifier */
7528                         return &klass->this_arg;
7529                 } else if (modval == -1) {
7530                         klass = mono_ptr_class_get (&klass->byval_arg);
7531                 } else if (modval == -2) {
7532                         bounded = TRUE;
7533                 } else { /* array rank */
7534                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7535                 }
7536         }
7537
7538         return &klass->byval_arg;
7539 }
7540
7541 /*
7542  * mono_reflection_get_type:
7543  * @image: a metadata context
7544  * @info: type description structure
7545  * @ignorecase: flag for case-insensitive string compares
7546  * @type_resolve: whenever type resolve was already tried
7547  *
7548  * Build a MonoType from the type description in @info.
7549  * 
7550  */
7551
7552 MonoType*
7553 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7554         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7555 }
7556
7557 static MonoType*
7558 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7559 {
7560         MonoReflectionAssemblyBuilder *abuilder;
7561         MonoType *type;
7562         int i;
7563
7564         g_assert (assembly->dynamic);
7565         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7566
7567         /* Enumerate all modules */
7568
7569         type = NULL;
7570         if (abuilder->modules) {
7571                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7572                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7573                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7574                         if (type)
7575                                 break;
7576                 }
7577         }
7578
7579         if (!type && abuilder->loaded_modules) {
7580                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7581                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7582                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7583                         if (type)
7584                                 break;
7585                 }
7586         }
7587
7588         return type;
7589 }
7590         
7591 MonoType*
7592 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7593 {
7594         MonoType *type;
7595         MonoReflectionAssembly *assembly;
7596         GString *fullName;
7597         GList *mod;
7598
7599         if (image && image->dynamic)
7600                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7601         else
7602                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7603         if (type)
7604                 return type;
7605         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7606                 return NULL;
7607
7608         if (type_resolve) {
7609                 if (*type_resolve) 
7610                         return NULL;
7611                 else
7612                         *type_resolve = TRUE;
7613         }
7614         
7615         /* Reconstruct the type name */
7616         fullName = g_string_new ("");
7617         if (info->name_space && (info->name_space [0] != '\0'))
7618                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7619         else
7620                 g_string_printf (fullName, "%s", info->name);
7621         for (mod = info->nested; mod; mod = mod->next)
7622                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7623
7624         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7625         if (assembly) {
7626                 if (assembly->assembly->dynamic)
7627                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7628                 else
7629                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7630                                                                                                           info, ignorecase);
7631         }
7632         g_string_free (fullName, TRUE);
7633         return type;
7634 }
7635
7636 void
7637 mono_reflection_free_type_info (MonoTypeNameParse *info)
7638 {
7639         g_list_free (info->modifiers);
7640         g_list_free (info->nested);
7641
7642         if (info->type_arguments) {
7643                 int i;
7644
7645                 for (i = 0; i < info->type_arguments->len; i++) {
7646                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7647
7648                         mono_reflection_free_type_info (subinfo);
7649                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7650                         g_free (subinfo);
7651                 }
7652
7653                 g_ptr_array_free (info->type_arguments, TRUE);
7654         }
7655 }
7656
7657 /*
7658  * mono_reflection_type_from_name:
7659  * @name: type name.
7660  * @image: a metadata context (can be NULL).
7661  *
7662  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7663  * it defaults to get the type from @image or, if @image is NULL or loading
7664  * from it fails, uses corlib.
7665  * 
7666  */
7667 MonoType*
7668 mono_reflection_type_from_name (char *name, MonoImage *image)
7669 {
7670         MonoType *type = NULL;
7671         MonoTypeNameParse info;
7672         char *tmp;
7673
7674         /* Make a copy since parse_type modifies its argument */
7675         tmp = g_strdup (name);
7676         
7677         /*g_print ("requested type %s\n", str);*/
7678         if (mono_reflection_parse_type (tmp, &info)) {
7679                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7680         }
7681
7682         g_free (tmp);
7683         mono_reflection_free_type_info (&info);
7684         return type;
7685 }
7686
7687 /*
7688  * mono_reflection_get_token:
7689  *
7690  *   Return the metadata token of OBJ which should be an object
7691  * representing a metadata element.
7692  */
7693 guint32
7694 mono_reflection_get_token (MonoObject *obj)
7695 {
7696         MonoClass *klass;
7697         guint32 token = 0;
7698
7699         klass = obj->vtable->klass;
7700
7701         if (strcmp (klass->name, "MethodBuilder") == 0) {
7702                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7703
7704                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7705         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7706                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7707
7708                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7709         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7710                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7711
7712                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7713         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7714                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7715                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7716         } else if (strcmp (klass->name, "MonoType") == 0) {
7717                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7718                 MonoClass *mc = mono_class_from_mono_type (type);
7719                 if (!mono_class_init (mc))
7720                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7721
7722                 token = mc->type_token;
7723         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7724                    strcmp (klass->name, "MonoMethod") == 0 ||
7725                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7726                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7727                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7728                 if (m->method->is_inflated) {
7729                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7730                         return inflated->declaring->token;
7731                 } else {
7732                         token = m->method->token;
7733                 }
7734         } else if (strcmp (klass->name, "MonoField") == 0) {
7735                 MonoReflectionField *f = (MonoReflectionField*)obj;
7736
7737                 if (is_field_on_inst (f->field)) {
7738                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7739                         int field_index = f->field - dgclass->fields;
7740                         MonoObject *obj;
7741
7742                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7743                         obj = dgclass->field_objects [field_index];
7744                         return mono_reflection_get_token (obj);
7745                 }
7746                 token = mono_class_get_field_token (f->field);
7747         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7748                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7749
7750                 token = mono_class_get_property_token (p->property);
7751         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7752                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7753
7754                 token = mono_class_get_event_token (p->event);
7755         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7756                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7757                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7758                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7759
7760                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7761         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7762                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7763
7764                 token = m->token;
7765         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7766                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7767         } else {
7768                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7769                 MonoException *ex = mono_get_exception_not_implemented (msg);
7770                 g_free (msg);
7771                 mono_raise_exception (ex);
7772         }
7773
7774         return token;
7775 }
7776
7777 static void*
7778 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7779 {
7780         int slen, type = t->type;
7781         MonoClass *tklass = t->data.klass;
7782
7783 handle_enum:
7784         switch (type) {
7785         case MONO_TYPE_U1:
7786         case MONO_TYPE_I1:
7787         case MONO_TYPE_BOOLEAN: {
7788                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7789                 *bval = *p;
7790                 *end = p + 1;
7791                 return bval;
7792         }
7793         case MONO_TYPE_CHAR:
7794         case MONO_TYPE_U2:
7795         case MONO_TYPE_I2: {
7796                 guint16 *val = g_malloc (sizeof (guint16));
7797                 *val = read16 (p);
7798                 *end = p + 2;
7799                 return val;
7800         }
7801 #if SIZEOF_VOID_P == 4
7802         case MONO_TYPE_U:
7803         case MONO_TYPE_I:
7804 #endif
7805         case MONO_TYPE_R4:
7806         case MONO_TYPE_U4:
7807         case MONO_TYPE_I4: {
7808                 guint32 *val = g_malloc (sizeof (guint32));
7809                 *val = read32 (p);
7810                 *end = p + 4;
7811                 return val;
7812         }
7813 #if SIZEOF_VOID_P == 8
7814         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7815         case MONO_TYPE_I:
7816 #endif
7817         case MONO_TYPE_U8:
7818         case MONO_TYPE_I8: {
7819                 guint64 *val = g_malloc (sizeof (guint64));
7820                 *val = read64 (p);
7821                 *end = p + 8;
7822                 return val;
7823         }
7824         case MONO_TYPE_R8: {
7825                 double *val = g_malloc (sizeof (double));
7826                 readr8 (p, val);
7827                 *end = p + 8;
7828                 return val;
7829         }
7830         case MONO_TYPE_VALUETYPE:
7831                 if (t->data.klass->enumtype) {
7832                         type = mono_class_enum_basetype (t->data.klass)->type;
7833                         goto handle_enum;
7834                 } else {
7835                         MonoClass *k =  t->data.klass;
7836                         
7837                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7838                                 guint64 *val = g_malloc (sizeof (guint64));
7839                                 *val = read64 (p);
7840                                 *end = p + 8;
7841                                 return val;
7842                         }
7843                 }
7844                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7845                 break;
7846                 
7847         case MONO_TYPE_STRING:
7848                 if (*p == (char)0xFF) {
7849                         *end = p + 1;
7850                         return NULL;
7851                 }
7852                 slen = mono_metadata_decode_value (p, &p);
7853                 *end = p + slen;
7854                 return mono_string_new_len (mono_domain_get (), p, slen);
7855         case MONO_TYPE_CLASS: {
7856                 char *n;
7857                 MonoType *t;
7858                 if (*p == (char)0xFF) {
7859                         *end = p + 1;
7860                         return NULL;
7861                 }
7862 handle_type:
7863                 slen = mono_metadata_decode_value (p, &p);
7864                 n = g_memdup (p, slen + 1);
7865                 n [slen] = 0;
7866                 t = mono_reflection_type_from_name (n, image);
7867                 if (!t)
7868                         g_warning ("Cannot load type '%s'", n);
7869                 g_free (n);
7870                 *end = p + slen;
7871                 if (t)
7872                         return mono_type_get_object (mono_domain_get (), t);
7873                 else
7874                         return NULL;
7875         }
7876         case MONO_TYPE_OBJECT: {
7877                 char subt = *p++;
7878                 MonoObject *obj;
7879                 MonoClass *subc = NULL;
7880                 void *val;
7881
7882                 if (subt == 0x50) {
7883                         goto handle_type;
7884                 } else if (subt == 0x0E) {
7885                         type = MONO_TYPE_STRING;
7886                         goto handle_enum;
7887                 } else if (subt == 0x1D) {
7888                         MonoType simple_type = {{0}};
7889                         int etype = *p;
7890                         p ++;
7891
7892                         type = MONO_TYPE_SZARRAY;
7893                         if (etype == 0x50) {
7894                                 tklass = mono_defaults.systemtype_class;
7895                         } else {
7896                                 if (etype == 0x51)
7897                                         /* See Partition II, Appendix B3 */
7898                                         etype = MONO_TYPE_OBJECT;
7899                                 simple_type.type = etype;
7900                                 tklass = mono_class_from_mono_type (&simple_type);
7901                         }
7902                         goto handle_enum;
7903                 } else if (subt == 0x55) {
7904                         char *n;
7905                         MonoType *t;
7906                         slen = mono_metadata_decode_value (p, &p);
7907                         n = g_memdup (p, slen + 1);
7908                         n [slen] = 0;
7909                         t = mono_reflection_type_from_name (n, image);
7910                         if (!t)
7911                                 g_error ("Cannot load type '%s'", n);
7912                         g_free (n);
7913                         p += slen;
7914                         subc = mono_class_from_mono_type (t);
7915                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7916                         MonoType simple_type = {{0}};
7917                         simple_type.type = subt;
7918                         subc = mono_class_from_mono_type (&simple_type);
7919                 } else {
7920                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7921                 }
7922                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7923                 obj = mono_object_new (mono_domain_get (), subc);
7924                 g_assert (!subc->has_references);
7925                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7926                 g_free (val);
7927                 return obj;
7928         }
7929         case MONO_TYPE_SZARRAY: {
7930                 MonoArray *arr;
7931                 guint32 i, alen, basetype;
7932                 alen = read32 (p);
7933                 p += 4;
7934                 if (alen == 0xffffffff) {
7935                         *end = p;
7936                         return NULL;
7937                 }
7938                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7939                 basetype = tklass->byval_arg.type;
7940                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7941                         basetype = mono_class_enum_basetype (tklass)->type;
7942                 switch (basetype)
7943                 {
7944                         case MONO_TYPE_U1:
7945                         case MONO_TYPE_I1:
7946                         case MONO_TYPE_BOOLEAN:
7947                                 for (i = 0; i < alen; i++) {
7948                                         MonoBoolean val = *p++;
7949                                         mono_array_set (arr, MonoBoolean, i, val);
7950                                 }
7951                                 break;
7952                         case MONO_TYPE_CHAR:
7953                         case MONO_TYPE_U2:
7954                         case MONO_TYPE_I2:
7955                                 for (i = 0; i < alen; i++) {
7956                                         guint16 val = read16 (p);
7957                                         mono_array_set (arr, guint16, i, val);
7958                                         p += 2;
7959                                 }
7960                                 break;
7961                         case MONO_TYPE_R4:
7962                         case MONO_TYPE_U4:
7963                         case MONO_TYPE_I4:
7964                                 for (i = 0; i < alen; i++) {
7965                                         guint32 val = read32 (p);
7966                                         mono_array_set (arr, guint32, i, val);
7967                                         p += 4;
7968                                 }
7969                                 break;
7970                         case MONO_TYPE_R8:
7971                                 for (i = 0; i < alen; i++) {
7972                                         double val;
7973                                         readr8 (p, &val);
7974                                         mono_array_set (arr, double, i, val);
7975                                         p += 8;
7976                                 }
7977                                 break;
7978                         case MONO_TYPE_U8:
7979                         case MONO_TYPE_I8:
7980                                 for (i = 0; i < alen; i++) {
7981                                         guint64 val = read64 (p);
7982                                         mono_array_set (arr, guint64, i, val);
7983                                         p += 8;
7984                                 }
7985                                 break;
7986                         case MONO_TYPE_CLASS:
7987                         case MONO_TYPE_OBJECT:
7988                         case MONO_TYPE_STRING:
7989                                 for (i = 0; i < alen; i++) {
7990                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7991                                         mono_array_setref (arr, i, item);
7992                                 }
7993                                 break;
7994                         default:
7995                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7996                 }
7997                 *end=p;
7998                 return arr;
7999         }
8000         default:
8001                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8002         }
8003         return NULL;
8004 }
8005
8006 static MonoObject*
8007 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8008 {
8009         static MonoClass *klass;
8010         static MonoMethod *ctor;
8011         MonoObject *retval;
8012         void *params [2], *unboxed;
8013
8014         if (!klass)
8015                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8016         if (!ctor)
8017                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8018         
8019         params [0] = mono_type_get_object (mono_domain_get (), t);
8020         params [1] = val;
8021         retval = mono_object_new (mono_domain_get (), klass);
8022         unboxed = mono_object_unbox (retval);
8023         mono_runtime_invoke (ctor, unboxed, params, NULL);
8024
8025         return retval;
8026 }
8027
8028 static MonoObject*
8029 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8030 {
8031         static MonoClass *klass;
8032         static MonoMethod *ctor;
8033         MonoObject *retval;
8034         void *unboxed, *params [2];
8035
8036         if (!klass)
8037                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8038         if (!ctor)
8039                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8040
8041         params [0] = minfo;
8042         params [1] = typedarg;
8043         retval = mono_object_new (mono_domain_get (), klass);
8044         unboxed = mono_object_unbox (retval);
8045         mono_runtime_invoke (ctor, unboxed, params, NULL);
8046
8047         return retval;
8048 }
8049
8050 static gboolean
8051 type_is_reference (MonoType *type)
8052 {
8053         switch (type->type) {
8054         case MONO_TYPE_BOOLEAN:
8055         case MONO_TYPE_CHAR:
8056         case MONO_TYPE_U:
8057         case MONO_TYPE_I:
8058         case MONO_TYPE_U1:
8059         case MONO_TYPE_I1:
8060         case MONO_TYPE_U2:
8061         case MONO_TYPE_I2:
8062         case MONO_TYPE_U4:
8063         case MONO_TYPE_I4:
8064         case MONO_TYPE_U8:
8065         case MONO_TYPE_I8:
8066         case MONO_TYPE_R8:
8067         case MONO_TYPE_R4:
8068         case MONO_TYPE_VALUETYPE:
8069                 return FALSE;
8070         default:
8071                 return TRUE;
8072         }
8073 }
8074
8075 static void
8076 free_param_data (MonoMethodSignature *sig, void **params) {
8077         int i;
8078         for (i = 0; i < sig->param_count; ++i) {
8079                 if (!type_is_reference (sig->params [i]))
8080                         g_free (params [i]);
8081         }
8082 }
8083
8084 /*
8085  * Find the field index in the metadata FieldDef table.
8086  */
8087 static guint32
8088 find_field_index (MonoClass *klass, MonoClassField *field) {
8089         int i;
8090
8091         for (i = 0; i < klass->field.count; ++i) {
8092                 if (field == &klass->fields [i])
8093                         return klass->field.first + 1 + i;
8094         }
8095         return 0;
8096 }
8097
8098 /*
8099  * Find the property index in the metadata Property table.
8100  */
8101 static guint32
8102 find_property_index (MonoClass *klass, MonoProperty *property) {
8103         int i;
8104
8105         for (i = 0; i < klass->ext->property.count; ++i) {
8106                 if (property == &klass->ext->properties [i])
8107                         return klass->ext->property.first + 1 + i;
8108         }
8109         return 0;
8110 }
8111
8112 /*
8113  * Find the event index in the metadata Event table.
8114  */
8115 static guint32
8116 find_event_index (MonoClass *klass, MonoEvent *event) {
8117         int i;
8118
8119         for (i = 0; i < klass->ext->event.count; ++i) {
8120                 if (event == &klass->ext->events [i])
8121                         return klass->ext->event.first + 1 + i;
8122         }
8123         return 0;
8124 }
8125
8126 static MonoObject*
8127 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8128 {
8129         const char *p = (const char*)data;
8130         const char *named;
8131         guint32 i, j, num_named;
8132         MonoObject *attr;
8133         void *params_buf [32];
8134         void **params;
8135         MonoMethodSignature *sig;
8136
8137         mono_error_init (error);
8138
8139         mono_class_init (method->klass);
8140
8141         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8142                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8143                 return NULL;
8144         }
8145
8146         if (len == 0) {
8147                 attr = mono_object_new (mono_domain_get (), method->klass);
8148                 mono_runtime_invoke (method, attr, NULL, NULL);
8149                 return attr;
8150         }
8151
8152         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8153                 return NULL;
8154
8155         /*g_print ("got attr %s\n", method->klass->name);*/
8156
8157         sig = mono_method_signature (method);
8158         if (sig->param_count < 32)
8159                 params = params_buf;
8160         else
8161                 /* Allocate using GC so it gets GC tracking */
8162                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8163
8164         /* skip prolog */
8165         p += 2;
8166         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8167                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8168         }
8169
8170         named = p;
8171         attr = mono_object_new (mono_domain_get (), method->klass);
8172         mono_runtime_invoke (method, attr, params, NULL);
8173         free_param_data (method->signature, params);
8174         num_named = read16 (named);
8175         named += 2;
8176         for (j = 0; j < num_named; j++) {
8177                 gint name_len;
8178                 char *name, named_type, data_type;
8179                 named_type = *named++;
8180                 data_type = *named++; /* type of data */
8181                 if (data_type == MONO_TYPE_SZARRAY)
8182                         data_type = *named++;
8183                 if (data_type == MONO_TYPE_ENUM) {
8184                         gint type_len;
8185                         char *type_name;
8186                         type_len = mono_metadata_decode_blob_size (named, &named);
8187                         type_name = g_malloc (type_len + 1);
8188                         memcpy (type_name, named, type_len);
8189                         type_name [type_len] = 0;
8190                         named += type_len;
8191                         /* FIXME: lookup the type and check type consistency */
8192                         g_free (type_name);
8193                 }
8194                 name_len = mono_metadata_decode_blob_size (named, &named);
8195                 name = g_malloc (name_len + 1);
8196                 memcpy (name, named, name_len);
8197                 name [name_len] = 0;
8198                 named += name_len;
8199                 if (named_type == 0x53) {
8200                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8201                         void *val = load_cattr_value (image, field->type, named, &named);
8202                         mono_field_set_value (attr, field, val);
8203                         if (!type_is_reference (field->type))
8204                                 g_free (val);
8205                 } else if (named_type == 0x54) {
8206                         MonoProperty *prop;
8207                         void *pparams [1];
8208                         MonoType *prop_type;
8209
8210                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8211                         /* can we have more that 1 arg in a custom attr named property? */
8212                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8213                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8214                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8215                         mono_property_set_value (prop, attr, pparams, NULL);
8216                         if (!type_is_reference (prop_type))
8217                                 g_free (pparams [0]);
8218                 }
8219                 g_free (name);
8220         }
8221
8222         if (params != params_buf)
8223                 mono_gc_free_fixed (params);
8224
8225         return attr;
8226 }
8227         
8228 /*
8229  * mono_reflection_create_custom_attr_data_args:
8230  *
8231  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8232  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8233  * NAMED_ARG_INFO will contain information about the named arguments.
8234  */
8235 void
8236 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info)
8237 {
8238         MonoArray *typedargs, *namedargs;
8239         MonoClass *attrklass;
8240         MonoDomain *domain;
8241         const char *p = (const char*)data;
8242         const char *named;
8243         guint32 i, j, num_named;
8244         CattrNamedArg *arginfo = NULL;
8245
8246         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8247                 return;
8248
8249         mono_class_init (method->klass);
8250
8251         *typed_args = NULL;
8252         *named_args = NULL;
8253         *named_arg_info = NULL;
8254         
8255         domain = mono_domain_get ();
8256
8257         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8258                 return;
8259
8260         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8261         
8262         /* skip prolog */
8263         p += 2;
8264         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8265                 MonoObject *obj;
8266                 void *val;
8267
8268                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8269                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8270                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8271                 mono_array_setref (typedargs, i, obj);
8272
8273                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8274                         g_free (val);
8275         }
8276
8277         named = p;
8278         num_named = read16 (named);
8279         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8280         named += 2;
8281         attrklass = method->klass;
8282
8283         arginfo = g_new0 (CattrNamedArg, num_named);
8284         *named_arg_info = arginfo;
8285
8286         for (j = 0; j < num_named; j++) {
8287                 gint name_len;
8288                 char *name, named_type, data_type;
8289                 named_type = *named++;
8290                 data_type = *named++; /* type of data */
8291                 if (data_type == MONO_TYPE_SZARRAY)
8292                         data_type = *named++;
8293                 if (data_type == MONO_TYPE_ENUM) {
8294                         gint type_len;
8295                         char *type_name;
8296                         type_len = mono_metadata_decode_blob_size (named, &named);
8297                         type_name = g_malloc (type_len + 1);
8298                         memcpy (type_name, named, type_len);
8299                         type_name [type_len] = 0;
8300                         named += type_len;
8301                         /* FIXME: lookup the type and check type consistency */
8302                         g_free (type_name);
8303                 }
8304                 name_len = mono_metadata_decode_blob_size (named, &named);
8305                 name = g_malloc (name_len + 1);
8306                 memcpy (name, named, name_len);
8307                 name [name_len] = 0;
8308                 named += name_len;
8309                 if (named_type == 0x53) {
8310                         MonoObject *obj;
8311                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8312                         void *val;
8313
8314                         arginfo [j].type = field->type;
8315                         arginfo [j].field = field;
8316
8317                         val = load_cattr_value (image, field->type, named, &named);
8318                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8319                         mono_array_setref (namedargs, j, obj);
8320                         if (!type_is_reference (field->type))
8321                                 g_free (val);
8322                 } else if (named_type == 0x54) {
8323                         MonoObject *obj;
8324                         MonoType *prop_type;
8325                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8326                         void *val;
8327
8328                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8329                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8330
8331                         arginfo [j].type = prop_type;
8332                         arginfo [j].prop = prop;
8333
8334                         val = load_cattr_value (image, prop_type, named, &named);
8335                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8336                         mono_array_setref (namedargs, j, obj);
8337                         if (!type_is_reference (prop_type))
8338                                 g_free (val);
8339                 }
8340                 g_free (name);
8341         }
8342
8343         *typed_args = typedargs;
8344         *named_args = namedargs;
8345 }
8346
8347 void
8348 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8349 {
8350         MonoDomain *domain;
8351         MonoArray *typedargs, *namedargs;
8352         MonoImage *image;
8353         MonoMethod *method;
8354         CattrNamedArg *arginfo;
8355         int i;
8356
8357         *ctor_args = NULL;
8358         *named_args = NULL;
8359
8360         if (len == 0)
8361                 return;
8362
8363         image = assembly->assembly->image;
8364         method = ref_method->method;
8365         domain = mono_object_domain (ref_method);
8366
8367         if (!mono_class_init (method->klass))
8368                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8369
8370         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8371         if (mono_loader_get_last_error ())
8372                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8373
8374         if (!typedargs || !namedargs)
8375                 return;
8376
8377         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8378                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8379                 MonoObject *typedarg;
8380
8381                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8382                 mono_array_setref (typedargs, i, typedarg);
8383         }
8384
8385         for (i = 0; i < mono_array_length (namedargs); ++i) {
8386                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8387                 MonoObject *typedarg, *namedarg, *minfo;
8388
8389                 if (arginfo [i].prop)
8390                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8391                 else
8392                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8393
8394                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8395                 namedarg = create_cattr_named_arg (minfo, typedarg);
8396
8397                 mono_array_setref (namedargs, i, namedarg);
8398         }
8399
8400         *ctor_args = typedargs;
8401         *named_args = namedargs;
8402 }
8403
8404 static MonoObject*
8405 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8406 {
8407         static MonoMethod *ctor;
8408         MonoDomain *domain;
8409         MonoObject *attr;
8410         void *params [4];
8411
8412         g_assert (image->assembly);
8413
8414         if (!ctor)
8415                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8416
8417         domain = mono_domain_get ();
8418         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8419         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8420         params [1] = mono_assembly_get_object (domain, image->assembly);
8421         params [2] = (gpointer)&cattr->data;
8422         params [3] = &cattr->data_size;
8423         mono_runtime_invoke (ctor, attr, params, NULL);
8424         return attr;
8425 }
8426
8427 static MonoArray*
8428 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8429 {
8430         MonoArray *result;
8431         MonoObject *attr;
8432         int i, n;
8433
8434         mono_error_init (error);
8435
8436         n = 0;
8437         for (i = 0; i < cinfo->num_attrs; ++i) {
8438                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8439                         n ++;
8440         }
8441
8442         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8443         n = 0;
8444         for (i = 0; i < cinfo->num_attrs; ++i) {
8445                 if (!cinfo->attrs [i].ctor)
8446                         /* The cattr type is not finished yet */
8447                         /* We should include the type name but cinfo doesn't contain it */
8448                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8449                 if (!attr_klass || 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, error);
8451                         if (!mono_error_ok (error))
8452                                 return result;
8453                         mono_array_setref (result, n, attr);
8454                         n ++;
8455                 }
8456         }
8457         return result;
8458 }
8459
8460 MonoArray*
8461 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8462 {
8463         MonoError error;
8464
8465         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8466 }
8467
8468 static MonoArray*
8469 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8470 {
8471         MonoArray *result;
8472         MonoObject *attr;
8473         int i;
8474         
8475         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8476         for (i = 0; i < cinfo->num_attrs; ++i) {
8477                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8478                 mono_array_setref (result, i, attr);
8479         }
8480         return result;
8481 }
8482
8483 /**
8484  * mono_custom_attrs_from_index:
8485  *
8486  * Returns: NULL if no attributes are found or if a loading error occurs.
8487  */
8488 MonoCustomAttrInfo*
8489 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8490 {
8491         guint32 mtoken, i, len;
8492         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8493         MonoTableInfo *ca;
8494         MonoCustomAttrInfo *ainfo;
8495         GList *tmp, *list = NULL;
8496         const char *data;
8497
8498         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8499
8500         i = mono_metadata_custom_attrs_from_index (image, idx);
8501         if (!i)
8502                 return NULL;
8503         i --;
8504         while (i < ca->rows) {
8505                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8506                         break;
8507                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8508                 ++i;
8509         }
8510         len = g_list_length (list);
8511         if (!len)
8512                 return NULL;
8513         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8514         ainfo->num_attrs = len;
8515         ainfo->image = image;
8516         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8517                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8518                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8519                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8520                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8521                         mtoken |= MONO_TOKEN_METHOD_DEF;
8522                         break;
8523                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8524                         mtoken |= MONO_TOKEN_MEMBER_REF;
8525                         break;
8526                 default:
8527                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8528                         break;
8529                 }
8530                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8531                 if (!ainfo->attrs [i].ctor) {
8532                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8533                         g_list_free (list);
8534                         g_free (ainfo);
8535                         return NULL;
8536                 }
8537
8538                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8539                         /*FIXME raising an exception here doesn't make any sense*/
8540                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8541                         g_list_free (list);
8542                         g_free (ainfo);
8543                         return NULL;
8544                 }
8545                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8546                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8547                 ainfo->attrs [i].data = (guchar*)data;
8548         }
8549         g_list_free (list);
8550
8551         return ainfo;
8552 }
8553
8554 MonoCustomAttrInfo*
8555 mono_custom_attrs_from_method (MonoMethod *method)
8556 {
8557         guint32 idx;
8558
8559         /*
8560          * An instantiated method has the same cattrs as the generic method definition.
8561          *
8562          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8563          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8564          */
8565         if (method->is_inflated)
8566                 method = ((MonoMethodInflated *) method)->declaring;
8567         
8568         if (method->dynamic || method->klass->image->dynamic)
8569                 return lookup_custom_attr (method->klass->image, method);
8570
8571         if (!method->token)
8572                 /* Synthetic methods */
8573                 return NULL;
8574
8575         idx = mono_method_get_index (method);
8576         idx <<= MONO_CUSTOM_ATTR_BITS;
8577         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8578         return mono_custom_attrs_from_index (method->klass->image, idx);
8579 }
8580
8581 MonoCustomAttrInfo*
8582 mono_custom_attrs_from_class (MonoClass *klass)
8583 {
8584         guint32 idx;
8585
8586         if (klass->generic_class)
8587                 klass = klass->generic_class->container_class;
8588
8589         if (klass->image->dynamic)
8590                 return lookup_custom_attr (klass->image, klass);
8591
8592         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8593                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8594                 idx <<= MONO_CUSTOM_ATTR_BITS;
8595                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8596         } else {
8597                 idx = mono_metadata_token_index (klass->type_token);
8598                 idx <<= MONO_CUSTOM_ATTR_BITS;
8599                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8600         }
8601         return mono_custom_attrs_from_index (klass->image, idx);
8602 }
8603
8604 MonoCustomAttrInfo*
8605 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8606 {
8607         guint32 idx;
8608         
8609         if (assembly->image->dynamic)
8610                 return lookup_custom_attr (assembly->image, assembly);
8611         idx = 1; /* there is only one assembly */
8612         idx <<= MONO_CUSTOM_ATTR_BITS;
8613         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8614         return mono_custom_attrs_from_index (assembly->image, idx);
8615 }
8616
8617 static MonoCustomAttrInfo*
8618 mono_custom_attrs_from_module (MonoImage *image)
8619 {
8620         guint32 idx;
8621         
8622         if (image->dynamic)
8623                 return lookup_custom_attr (image, image);
8624         idx = 1; /* there is only one module */
8625         idx <<= MONO_CUSTOM_ATTR_BITS;
8626         idx |= MONO_CUSTOM_ATTR_MODULE;
8627         return mono_custom_attrs_from_index (image, idx);
8628 }
8629
8630 MonoCustomAttrInfo*
8631 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8632 {
8633         guint32 idx;
8634         
8635         if (klass->image->dynamic) {
8636                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8637                 return lookup_custom_attr (klass->image, property);
8638         }
8639         idx = find_property_index (klass, property);
8640         idx <<= MONO_CUSTOM_ATTR_BITS;
8641         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8642         return mono_custom_attrs_from_index (klass->image, idx);
8643 }
8644
8645 MonoCustomAttrInfo*
8646 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8647 {
8648         guint32 idx;
8649         
8650         if (klass->image->dynamic) {
8651                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8652                 return lookup_custom_attr (klass->image, event);
8653         }
8654         idx = find_event_index (klass, event);
8655         idx <<= MONO_CUSTOM_ATTR_BITS;
8656         idx |= MONO_CUSTOM_ATTR_EVENT;
8657         return mono_custom_attrs_from_index (klass->image, idx);
8658 }
8659
8660 MonoCustomAttrInfo*
8661 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8662 {
8663         guint32 idx;
8664         if (klass->image->dynamic) {
8665                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8666                 return lookup_custom_attr (klass->image, field);
8667         }
8668         idx = find_field_index (klass, field);
8669         idx <<= MONO_CUSTOM_ATTR_BITS;
8670         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8671         return mono_custom_attrs_from_index (klass->image, idx);
8672 }
8673
8674 MonoCustomAttrInfo*
8675 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8676 {
8677         MonoTableInfo *ca;
8678         guint32 i, idx, method_index;
8679         guint32 param_list, param_last, param_pos, found;
8680         MonoImage *image;
8681         MonoReflectionMethodAux *aux;
8682
8683         /*
8684          * An instantiated method has the same cattrs as the generic method definition.
8685          *
8686          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8687          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8688          */
8689         if (method->is_inflated)
8690                 method = ((MonoMethodInflated *) method)->declaring;
8691
8692         if (method->klass->image->dynamic) {
8693                 MonoCustomAttrInfo *res, *ainfo;
8694                 int size;
8695
8696                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8697                 if (!aux || !aux->param_cattr)
8698                         return NULL;
8699
8700                 /* Need to copy since it will be freed later */
8701                 ainfo = aux->param_cattr [param];
8702                 if (!ainfo)
8703                         return NULL;
8704                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8705                 res = g_malloc0 (size);
8706                 memcpy (res, ainfo, size);
8707                 return res;
8708         }
8709
8710         image = method->klass->image;
8711         method_index = mono_method_get_index (method);
8712         if (!method_index)
8713                 return NULL;
8714         ca = &image->tables [MONO_TABLE_METHOD];
8715
8716         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8717         if (method_index == ca->rows) {
8718                 ca = &image->tables [MONO_TABLE_PARAM];
8719                 param_last = ca->rows + 1;
8720         } else {
8721                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8722                 ca = &image->tables [MONO_TABLE_PARAM];
8723         }
8724         found = FALSE;
8725         for (i = param_list; i < param_last; ++i) {
8726                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8727                 if (param_pos == param) {
8728                         found = TRUE;
8729                         break;
8730                 }
8731         }
8732         if (!found)
8733                 return NULL;
8734         idx = i;
8735         idx <<= MONO_CUSTOM_ATTR_BITS;
8736         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8737         return mono_custom_attrs_from_index (image, idx);
8738 }
8739
8740 gboolean
8741 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8742 {
8743         int i;
8744         MonoClass *klass;
8745         for (i = 0; i < ainfo->num_attrs; ++i) {
8746                 klass = ainfo->attrs [i].ctor->klass;
8747                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8748                         return TRUE;
8749         }
8750         return FALSE;
8751 }
8752
8753 MonoObject*
8754 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8755 {
8756         int i, attr_index;
8757         MonoClass *klass;
8758         MonoArray *attrs;
8759
8760         attr_index = -1;
8761         for (i = 0; i < ainfo->num_attrs; ++i) {
8762                 klass = ainfo->attrs [i].ctor->klass;
8763                 if (mono_class_has_parent (klass, attr_klass)) {
8764                         attr_index = i;
8765                         break;
8766                 }
8767         }
8768         if (attr_index == -1)
8769                 return NULL;
8770
8771         attrs = mono_custom_attrs_construct (ainfo);
8772         if (attrs)
8773                 return mono_array_get (attrs, MonoObject*, attr_index);
8774         else
8775                 return NULL;
8776 }
8777
8778 /*
8779  * mono_reflection_get_custom_attrs_info:
8780  * @obj: a reflection object handle
8781  *
8782  * Return the custom attribute info for attributes defined for the
8783  * reflection handle @obj. The objects.
8784  *
8785  * FIXME this function leaks like a sieve for SRE objects.
8786  */
8787 MonoCustomAttrInfo*
8788 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8789 {
8790         MonoClass *klass;
8791         MonoCustomAttrInfo *cinfo = NULL;
8792         
8793         klass = obj->vtable->klass;
8794         if (klass == mono_defaults.monotype_class) {
8795                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8796                 klass = mono_class_from_mono_type (type);
8797                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8798                 cinfo = mono_custom_attrs_from_class (klass);
8799         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8800                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8801                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8802         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8803                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8804                 cinfo = mono_custom_attrs_from_module (module->image);
8805         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8806                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8807                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8808         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8809                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8810                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8811         } else if (strcmp ("MonoField", klass->name) == 0) {
8812                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8813                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8814         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8815                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8816                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8817         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8818                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8819                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8820         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8821                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8822                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8823                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8824                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8825                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8826                 } else if (is_sr_mono_property (member_class)) {
8827                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8828                         MonoMethod *method;
8829                         if (!(method = prop->property->get))
8830                                 method = prop->property->set;
8831                         g_assert (method);
8832
8833                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8834                 } 
8835 #ifndef DISABLE_REFLECTION_EMIT
8836                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8837                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8838                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8839                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8840                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8841                         MonoMethod *method = NULL;
8842                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8843                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8844                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8845                                 method = ((MonoReflectionMethod *)c->cb)->method;
8846                         else
8847                                 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));
8848
8849                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8850                 } 
8851 #endif
8852                 else {
8853                         char *type_name = mono_type_get_full_name (member_class);
8854                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8855                         MonoException *ex = mono_get_exception_not_supported  (msg);
8856                         g_free (type_name);
8857                         g_free (msg);
8858                         mono_raise_exception (ex);
8859                 }
8860         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8861                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8862                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8863         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8864                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8865                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8866         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8867                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8868                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8869         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8870                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8871                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8872         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8873                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8874                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8875         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8876                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8877                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8878         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8879                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8880                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8881         } else { /* handle other types here... */
8882                 g_error ("get custom attrs not yet supported for %s", klass->name);
8883         }
8884
8885         return cinfo;
8886 }
8887
8888 /*
8889  * mono_reflection_get_custom_attrs_by_type:
8890  * @obj: a reflection object handle
8891  *
8892  * Return an array with all the custom attributes defined of the
8893  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8894  * of that type are returned. The objects are fully build. Return NULL if a loading error
8895  * occurs.
8896  */
8897 MonoArray*
8898 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8899 {
8900         MonoArray *result;
8901         MonoCustomAttrInfo *cinfo;
8902
8903         mono_error_init (error);
8904
8905         cinfo = mono_reflection_get_custom_attrs_info (obj);
8906         if (cinfo) {
8907                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8908                 if (!cinfo->cached)
8909                         mono_custom_attrs_free (cinfo);
8910         } else {
8911                 if (mono_loader_get_last_error ())
8912                         return NULL;
8913                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8914         }
8915
8916         return result;
8917 }
8918
8919 /*
8920  * mono_reflection_get_custom_attrs:
8921  * @obj: a reflection object handle
8922  *
8923  * Return an array with all the custom attributes defined of the
8924  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8925  * occurs.
8926  */
8927 MonoArray*
8928 mono_reflection_get_custom_attrs (MonoObject *obj)
8929 {
8930         MonoError error;
8931
8932         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8933 }
8934
8935 /*
8936  * mono_reflection_get_custom_attrs_data:
8937  * @obj: a reflection obj handle
8938  *
8939  * Returns an array of System.Reflection.CustomAttributeData,
8940  * which include information about attributes reflected on
8941  * types loaded using the Reflection Only methods
8942  */
8943 MonoArray*
8944 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8945 {
8946         MonoArray *result;
8947         MonoCustomAttrInfo *cinfo;
8948
8949         cinfo = mono_reflection_get_custom_attrs_info (obj);
8950         if (cinfo) {
8951                 result = mono_custom_attrs_data_construct (cinfo);
8952                 if (!cinfo->cached)
8953                         mono_custom_attrs_free (cinfo);
8954         } else
8955                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8956
8957         return result;
8958 }
8959
8960 static MonoReflectionType*
8961 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8962 {
8963         static MonoMethod *method_get_underlying_system_type = NULL;
8964         MonoMethod *usertype_method;
8965
8966         if (!method_get_underlying_system_type)
8967                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8968         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8969         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8970 }
8971
8972
8973 static gboolean
8974 is_corlib_type (MonoClass *class)
8975 {
8976         return class->image == mono_defaults.corlib;
8977 }
8978
8979 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8980         static MonoClass *cached_class; \
8981         if (cached_class) \
8982                 return cached_class == _class; \
8983         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8984                 cached_class = _class; \
8985                 return TRUE; \
8986         } \
8987         return FALSE; \
8988 } while (0) \
8989
8990
8991 #ifndef DISABLE_REFLECTION_EMIT
8992 static gboolean
8993 is_sre_array (MonoClass *class)
8994 {
8995         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8996 }
8997
8998 static gboolean
8999 is_sre_byref (MonoClass *class)
9000 {
9001         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9002 }
9003
9004 static gboolean
9005 is_sre_pointer (MonoClass *class)
9006 {
9007         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9008 }
9009
9010 static gboolean
9011 is_sre_generic_instance (MonoClass *class)
9012 {
9013         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9014 }
9015
9016 static gboolean
9017 is_sre_type_builder (MonoClass *class)
9018 {
9019         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9020 }
9021
9022 static gboolean
9023 is_sre_method_builder (MonoClass *class)
9024 {
9025         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9026 }
9027
9028 static gboolean
9029 is_sre_ctor_builder (MonoClass *class)
9030 {
9031         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9032 }
9033
9034 static gboolean
9035 is_sre_field_builder (MonoClass *class)
9036 {
9037         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9038 }
9039
9040 static gboolean
9041 is_sre_method_on_tb_inst (MonoClass *class)
9042 {
9043         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9044 }
9045
9046 static gboolean
9047 is_sre_ctor_on_tb_inst (MonoClass *class)
9048 {
9049         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9050 }
9051
9052 MonoType*
9053 mono_reflection_type_get_handle (MonoReflectionType* ref)
9054 {
9055         MonoClass *class;
9056         if (!ref)
9057                 return NULL;
9058         if (ref->type)
9059                 return ref->type;
9060
9061         if (is_usertype (ref)) {
9062                 ref = mono_reflection_type_get_underlying_system_type (ref);
9063                 if (ref == NULL || is_usertype (ref))
9064                         return NULL;
9065                 if (ref->type)
9066                         return ref->type;
9067         }
9068
9069         class = mono_object_class (ref);
9070
9071         if (is_sre_array (class)) {
9072                 MonoType *res;
9073                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9074                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9075                 g_assert (base);
9076                 if (sre_array->rank == 0) //single dimentional array
9077                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9078                 else
9079                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9080                 sre_array->type.type = res;
9081                 return res;
9082         } else if (is_sre_byref (class)) {
9083                 MonoType *res;
9084                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9085                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9086                 g_assert (base);
9087                 res = &mono_class_from_mono_type (base)->this_arg;
9088                 sre_byref->type.type = res;
9089                 return res;
9090         } else if (is_sre_pointer (class)) {
9091                 MonoType *res;
9092                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9093                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9094                 g_assert (base);
9095                 res = &mono_ptr_class_get (base)->byval_arg;
9096                 sre_pointer->type.type = res;
9097                 return res;
9098         } else if (is_sre_generic_instance (class)) {
9099                 MonoType *res, **types;
9100                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9101                 int i, count;
9102
9103                 count = mono_array_length (gclass->type_arguments);
9104                 types = g_new0 (MonoType*, count);
9105                 for (i = 0; i < count; ++i) {
9106                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9107                         types [i] = mono_reflection_type_get_handle (t);
9108                         if (!types[i]) {
9109                                 g_free (types);
9110                                 return NULL;
9111                         }
9112                 }
9113
9114                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9115                 g_free (types);
9116                 g_assert (res);
9117                 gclass->type.type = res;
9118                 return res;
9119         }
9120
9121         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9122         return NULL;
9123 }
9124
9125
9126
9127 void
9128 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9129 {
9130         mono_reflection_type_get_handle (type);
9131 }
9132
9133 void
9134 mono_reflection_register_with_runtime (MonoReflectionType *type)
9135 {
9136         MonoType *res = mono_reflection_type_get_handle (type);
9137         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9138         MonoClass *class;
9139
9140         if (!res)
9141                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9142
9143         class = mono_class_from_mono_type (res);
9144
9145         mono_loader_lock (); /*same locking as mono_type_get_object*/
9146         mono_domain_lock (domain);
9147
9148         if (!class->image->dynamic) {
9149                 mono_class_setup_supertypes (class);
9150         } else {
9151                 if (!domain->type_hash)
9152                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9153                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9154                 mono_g_hash_table_insert (domain->type_hash, res, type);
9155         }
9156         mono_domain_unlock (domain);
9157         mono_loader_unlock ();
9158 }
9159
9160 /**
9161  * LOCKING: Assumes the loader lock is held.
9162  */
9163 static MonoMethodSignature*
9164 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9165         MonoMethodSignature *sig;
9166         int count, i;
9167
9168         count = parameters? mono_array_length (parameters): 0;
9169
9170         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9171         sig->param_count = count;
9172         sig->sentinelpos = -1; /* FIXME */
9173         for (i = 0; i < count; ++i)
9174                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9175         return sig;
9176 }
9177
9178 /**
9179  * LOCKING: Assumes the loader lock is held.
9180  */
9181 static MonoMethodSignature*
9182 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9183         MonoMethodSignature *sig;
9184
9185         sig = parameters_to_signature (image, ctor->parameters);
9186         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9187         sig->ret = &mono_defaults.void_class->byval_arg;
9188         return sig;
9189 }
9190
9191 /**
9192  * LOCKING: Assumes the loader lock is held.
9193  */
9194 static MonoMethodSignature*
9195 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9196         MonoMethodSignature *sig;
9197
9198         sig = parameters_to_signature (image, method->parameters);
9199         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9200         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9201         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9202         return sig;
9203 }
9204
9205 static MonoMethodSignature*
9206 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9207         MonoMethodSignature *sig;
9208
9209         sig = parameters_to_signature (NULL, method->parameters);
9210         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9211         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9212         sig->generic_param_count = 0;
9213         return sig;
9214 }
9215
9216 static void
9217 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9218 {
9219         MonoClass *klass = mono_object_class (prop);
9220         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9221                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9222                 *name = mono_string_to_utf8 (pb->name);
9223                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9224         } else {
9225                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9226                 *name = g_strdup (p->property->name);
9227                 if (p->property->get)
9228                         *type = mono_method_signature (p->property->get)->ret;
9229                 else
9230                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9231         }
9232 }
9233
9234 static void
9235 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9236 {
9237         MonoClass *klass = mono_object_class (field);
9238         if (strcmp (klass->name, "FieldBuilder") == 0) {
9239                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9240                 *name = mono_string_to_utf8 (fb->name);
9241                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9242         } else {
9243                 MonoReflectionField *f = (MonoReflectionField *)field;
9244                 *name = g_strdup (mono_field_get_name (f->field));
9245                 *type = f->field->type;
9246         }
9247 }
9248
9249 #else /* DISABLE_REFLECTION_EMIT */
9250
9251 void
9252 mono_reflection_register_with_runtime (MonoReflectionType *type)
9253 {
9254         /* This is empty */
9255 }
9256
9257 static gboolean
9258 is_sre_type_builder (MonoClass *class)
9259 {
9260         return FALSE;
9261 }
9262
9263 static gboolean
9264 is_sre_generic_instance (MonoClass *class)
9265 {
9266         return FALSE;
9267 }
9268
9269 static void
9270 init_type_builder_generics (MonoObject *type)
9271 {
9272 }
9273
9274 #endif /* !DISABLE_REFLECTION_EMIT */
9275
9276
9277 static gboolean
9278 is_sr_mono_field (MonoClass *class)
9279 {
9280         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9281 }
9282
9283 static gboolean
9284 is_sr_mono_property (MonoClass *class)
9285 {
9286         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9287 }
9288
9289 static gboolean
9290 is_sr_mono_method (MonoClass *class)
9291 {
9292         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9293 }
9294
9295 static gboolean
9296 is_sr_mono_cmethod (MonoClass *class)
9297 {
9298         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9299 }
9300
9301 static gboolean
9302 is_sr_mono_generic_method (MonoClass *class)
9303 {
9304         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9305 }
9306
9307 static gboolean
9308 is_sr_mono_generic_cmethod (MonoClass *class)
9309 {
9310         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9311 }
9312
9313 gboolean
9314 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9315 {
9316         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9317 }
9318
9319 static gboolean
9320 is_usertype (MonoReflectionType *ref)
9321 {
9322         MonoClass *class = mono_object_class (ref);
9323         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9324 }
9325
9326 static MonoReflectionType*
9327 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9328 {
9329         if (!type || type->type)
9330                 return type;
9331
9332         if (is_usertype (type)) {
9333                 type = mono_reflection_type_get_underlying_system_type (type);
9334                 if (is_usertype (type))
9335                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9336         }
9337
9338         return type;
9339 }
9340 /*
9341  * Encode a value in a custom attribute stream of bytes.
9342  * The value to encode is either supplied as an object in argument val
9343  * (valuetypes are boxed), or as a pointer to the data in the
9344  * argument argval.
9345  * @type represents the type of the value
9346  * @buffer is the start of the buffer
9347  * @p the current position in the buffer
9348  * @buflen contains the size of the buffer and is used to return the new buffer size
9349  * if this needs to be realloced.
9350  * @retbuffer and @retp return the start and the position of the buffer
9351  */
9352 static void
9353 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9354 {
9355         MonoTypeEnum simple_type;
9356         
9357         if ((p-buffer) + 10 >= *buflen) {
9358                 char *newbuf;
9359                 *buflen *= 2;
9360                 newbuf = g_realloc (buffer, *buflen);
9361                 p = newbuf + (p-buffer);
9362                 buffer = newbuf;
9363         }
9364         if (!argval)
9365                 argval = ((char*)arg + sizeof (MonoObject));
9366         simple_type = type->type;
9367 handle_enum:
9368         switch (simple_type) {
9369         case MONO_TYPE_BOOLEAN:
9370         case MONO_TYPE_U1:
9371         case MONO_TYPE_I1:
9372                 *p++ = *argval;
9373                 break;
9374         case MONO_TYPE_CHAR:
9375         case MONO_TYPE_U2:
9376         case MONO_TYPE_I2:
9377                 swap_with_size (p, argval, 2, 1);
9378                 p += 2;
9379                 break;
9380         case MONO_TYPE_U4:
9381         case MONO_TYPE_I4:
9382         case MONO_TYPE_R4:
9383                 swap_with_size (p, argval, 4, 1);
9384                 p += 4;
9385                 break;
9386         case MONO_TYPE_R8:
9387                 swap_with_size (p, argval, 8, 1);
9388                 p += 8;
9389                 break;
9390         case MONO_TYPE_U8:
9391         case MONO_TYPE_I8:
9392                 swap_with_size (p, argval, 8, 1);
9393                 p += 8;
9394                 break;
9395         case MONO_TYPE_VALUETYPE:
9396                 if (type->data.klass->enumtype) {
9397                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9398                         goto handle_enum;
9399                 } else {
9400                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9401                 }
9402                 break;
9403         case MONO_TYPE_STRING: {
9404                 char *str;
9405                 guint32 slen;
9406                 if (!arg) {
9407                         *p++ = 0xFF;
9408                         break;
9409                 }
9410                 str = mono_string_to_utf8 ((MonoString*)arg);
9411                 slen = strlen (str);
9412                 if ((p-buffer) + 10 + slen >= *buflen) {
9413                         char *newbuf;
9414                         *buflen *= 2;
9415                         *buflen += slen;
9416                         newbuf = g_realloc (buffer, *buflen);
9417                         p = newbuf + (p-buffer);
9418                         buffer = newbuf;
9419                 }
9420                 mono_metadata_encode_value (slen, p, &p);
9421                 memcpy (p, str, slen);
9422                 p += slen;
9423                 g_free (str);
9424                 break;
9425         }
9426         case MONO_TYPE_CLASS: {
9427                 char *str;
9428                 guint32 slen;
9429                 if (!arg) {
9430                         *p++ = 0xFF;
9431                         break;
9432                 }
9433 handle_type:
9434                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9435                 slen = strlen (str);
9436                 if ((p-buffer) + 10 + slen >= *buflen) {
9437                         char *newbuf;
9438                         *buflen *= 2;
9439                         *buflen += slen;
9440                         newbuf = g_realloc (buffer, *buflen);
9441                         p = newbuf + (p-buffer);
9442                         buffer = newbuf;
9443                 }
9444                 mono_metadata_encode_value (slen, p, &p);
9445                 memcpy (p, str, slen);
9446                 p += slen;
9447                 g_free (str);
9448                 break;
9449         }
9450         case MONO_TYPE_SZARRAY: {
9451                 int len, i;
9452                 MonoClass *eclass, *arg_eclass;
9453
9454                 if (!arg) {
9455                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9456                         break;
9457                 }
9458                 len = mono_array_length ((MonoArray*)arg);
9459                 *p++ = len & 0xff;
9460                 *p++ = (len >> 8) & 0xff;
9461                 *p++ = (len >> 16) & 0xff;
9462                 *p++ = (len >> 24) & 0xff;
9463                 *retp = p;
9464                 *retbuffer = buffer;
9465                 eclass = type->data.klass;
9466                 arg_eclass = mono_object_class (arg)->element_class;
9467
9468                 if (!eclass) {
9469                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9470                         eclass = mono_defaults.object_class;
9471                 }
9472                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9473                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9474                         int elsize = mono_class_array_element_size (arg_eclass);
9475                         for (i = 0; i < len; ++i) {
9476                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9477                                 elptr += elsize;
9478                         }
9479                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9480                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9481                         int elsize = mono_class_array_element_size (eclass);
9482                         for (i = 0; i < len; ++i) {
9483                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9484                                 elptr += elsize;
9485                         }
9486                 } else {
9487                         for (i = 0; i < len; ++i) {
9488                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9489                         }
9490                 }
9491                 break;
9492         }
9493         case MONO_TYPE_OBJECT: {
9494                 MonoClass *klass;
9495                 char *str;
9496                 guint32 slen;
9497
9498                 /*
9499                  * The parameter type is 'object' but the type of the actual
9500                  * argument is not. So we have to add type information to the blob
9501                  * too. This is completely undocumented in the spec.
9502                  */
9503
9504                 if (arg == NULL) {
9505                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9506                         *p++ = 0xFF;
9507                         break;
9508                 }
9509                 
9510                 klass = mono_object_class (arg);
9511
9512                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9513                         *p++ = 0x50;
9514                         goto handle_type;
9515                 } else if (klass->enumtype) {
9516                         *p++ = 0x55;
9517                 } else if (klass == mono_defaults.string_class) {
9518                         simple_type = MONO_TYPE_STRING;
9519                         *p++ = 0x0E;
9520                         goto handle_enum;
9521                 } else if (klass->rank == 1) {
9522                         *p++ = 0x1D;
9523                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9524                                 /* See Partition II, Appendix B3 */
9525                                 *p++ = 0x51;
9526                         else
9527                                 *p++ = klass->element_class->byval_arg.type;
9528                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9529                         break;
9530                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9531                         *p++ = simple_type = klass->byval_arg.type;
9532                         goto handle_enum;
9533                 } else {
9534                         g_error ("unhandled type in custom attr");
9535                 }
9536                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9537                 slen = strlen (str);
9538                 if ((p-buffer) + 10 + slen >= *buflen) {
9539                         char *newbuf;
9540                         *buflen *= 2;
9541                         *buflen += slen;
9542                         newbuf = g_realloc (buffer, *buflen);
9543                         p = newbuf + (p-buffer);
9544                         buffer = newbuf;
9545                 }
9546                 mono_metadata_encode_value (slen, p, &p);
9547                 memcpy (p, str, slen);
9548                 p += slen;
9549                 g_free (str);
9550                 simple_type = mono_class_enum_basetype (klass)->type;
9551                 goto handle_enum;
9552         }
9553         default:
9554                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9555         }
9556         *retp = p;
9557         *retbuffer = buffer;
9558 }
9559
9560 static void
9561 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9562 {
9563         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9564                 char *str = type_get_qualified_name (type, NULL);
9565                 int slen = strlen (str);
9566
9567                 *p++ = 0x55;
9568                 /*
9569                  * This seems to be optional...
9570                  * *p++ = 0x80;
9571                  */
9572                 mono_metadata_encode_value (slen, p, &p);
9573                 memcpy (p, str, slen);
9574                 p += slen;
9575                 g_free (str);
9576         } else if (type->type == MONO_TYPE_OBJECT) {
9577                 *p++ = 0x51;
9578         } else if (type->type == MONO_TYPE_CLASS) {
9579                 /* it should be a type: encode_cattr_value () has the check */
9580                 *p++ = 0x50;
9581         } else {
9582                 mono_metadata_encode_value (type->type, p, &p);
9583                 if (type->type == MONO_TYPE_SZARRAY)
9584                         /* See the examples in Partition VI, Annex B */
9585                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9586         }
9587
9588         *retp = p;
9589 }
9590
9591 #ifndef DISABLE_REFLECTION_EMIT
9592 static void
9593 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9594 {
9595         int len;
9596         /* Preallocate a large enough buffer */
9597         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9598                 char *str = type_get_qualified_name (type, NULL);
9599                 len = strlen (str);
9600                 g_free (str);
9601         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9602                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9603                 len = strlen (str);
9604                 g_free (str);
9605         } else {
9606                 len = 0;
9607         }
9608         len += strlen (name);
9609
9610         if ((p-buffer) + 20 + len >= *buflen) {
9611                 char *newbuf;
9612                 *buflen *= 2;
9613                 *buflen += len;
9614                 newbuf = g_realloc (buffer, *buflen);
9615                 p = newbuf + (p-buffer);
9616                 buffer = newbuf;
9617         }
9618
9619         encode_field_or_prop_type (type, p, &p);
9620
9621         len = strlen (name);
9622         mono_metadata_encode_value (len, p, &p);
9623         memcpy (p, name, len);
9624         p += len;
9625         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9626         *retp = p;
9627         *retbuffer = buffer;
9628 }
9629
9630 /*
9631  * mono_reflection_get_custom_attrs_blob:
9632  * @ctor: custom attribute constructor
9633  * @ctorArgs: arguments o the constructor
9634  * @properties:
9635  * @propValues:
9636  * @fields:
9637  * @fieldValues:
9638  * 
9639  * Creates the blob of data that needs to be saved in the metadata and that represents
9640  * the custom attributed described by @ctor, @ctorArgs etc.
9641  * Returns: a Byte array representing the blob of data.
9642  */
9643 MonoArray*
9644 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9645 {
9646         MonoArray *result;
9647         MonoMethodSignature *sig;
9648         MonoObject *arg;
9649         char *buffer, *p;
9650         guint32 buflen, i;
9651
9652         MONO_ARCH_SAVE_REGS;
9653
9654         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9655                 /* sig is freed later so allocate it in the heap */
9656                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9657         } else {
9658                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9659         }
9660
9661         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9662         buflen = 256;
9663         p = buffer = g_malloc (buflen);
9664         /* write the prolog */
9665         *p++ = 1;
9666         *p++ = 0;
9667         for (i = 0; i < sig->param_count; ++i) {
9668                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9669                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9670         }
9671         i = 0;
9672         if (properties)
9673                 i += mono_array_length (properties);
9674         if (fields)
9675                 i += mono_array_length (fields);
9676         *p++ = i & 0xff;
9677         *p++ = (i >> 8) & 0xff;
9678         if (properties) {
9679                 MonoObject *prop;
9680                 for (i = 0; i < mono_array_length (properties); ++i) {
9681                         MonoType *ptype;
9682                         char *pname;
9683
9684                         prop = mono_array_get (properties, gpointer, i);
9685                         get_prop_name_and_type (prop, &pname, &ptype);
9686                         *p++ = 0x54; /* PROPERTY signature */
9687                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9688                         g_free (pname);
9689                 }
9690         }
9691
9692         if (fields) {
9693                 MonoObject *field;
9694                 for (i = 0; i < mono_array_length (fields); ++i) {
9695                         MonoType *ftype;
9696                         char *fname;
9697
9698                         field = mono_array_get (fields, gpointer, i);
9699                         get_field_name_and_type (field, &fname, &ftype);
9700                         *p++ = 0x53; /* FIELD signature */
9701                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9702                         g_free (fname);
9703                 }
9704         }
9705
9706         g_assert (p - buffer <= buflen);
9707         buflen = p - buffer;
9708         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9709         p = mono_array_addr (result, char, 0);
9710         memcpy (p, buffer, buflen);
9711         g_free (buffer);
9712         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9713                 g_free (sig);
9714         return result;
9715 }
9716
9717 /*
9718  * mono_reflection_setup_internal_class:
9719  * @tb: a TypeBuilder object
9720  *
9721  * Creates a MonoClass that represents the TypeBuilder.
9722  * This is a trick that lets us simplify a lot of reflection code
9723  * (and will allow us to support Build and Run assemblies easier).
9724  */
9725 void
9726 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9727 {
9728         MonoError error;
9729         MonoClass *klass, *parent;
9730
9731         MONO_ARCH_SAVE_REGS;
9732
9733         RESOLVE_TYPE (tb->parent);
9734
9735         mono_loader_lock ();
9736
9737         if (tb->parent) {
9738                 /* check so we can compile corlib correctly */
9739                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9740                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9741                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9742                 } else {
9743                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9744                 }
9745         } else {
9746                 parent = NULL;
9747         }
9748         
9749         /* the type has already being created: it means we just have to change the parent */
9750         if (tb->type.type) {
9751                 klass = mono_class_from_mono_type (tb->type.type);
9752                 klass->parent = NULL;
9753                 /* fool mono_class_setup_parent */
9754                 klass->supertypes = NULL;
9755                 mono_class_setup_parent (klass, parent);
9756                 mono_class_setup_mono_type (klass);
9757                 mono_loader_unlock ();
9758                 return;
9759         }
9760
9761         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9762
9763         klass->image = &tb->module->dynamic_image->image;
9764
9765         klass->inited = 1; /* we lie to the runtime */
9766         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9767         if (!mono_error_ok (&error))
9768                 goto failure;
9769         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9770         if (!mono_error_ok (&error))
9771                 goto failure;
9772         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9773         klass->flags = tb->attrs;
9774         
9775         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9776
9777         klass->element_class = klass;
9778
9779         if (mono_class_get_ref_info (klass) == NULL) {
9780
9781                 mono_class_set_ref_info (klass, tb);
9782
9783                 /* Put into cache so mono_class_get () will find it.
9784                 Skip nested types as those should not be available on the global scope. */
9785                 if (!tb->nesting_type) {
9786                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9787                 } else {
9788                         klass->image->reflection_info_unregister_classes =
9789                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9790                 }
9791         } else {
9792                 g_assert (mono_class_get_ref_info (klass) == tb);
9793         }
9794
9795         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9796                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9797
9798         if (parent != NULL) {
9799                 mono_class_setup_parent (klass, parent);
9800         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9801                 const char *old_n = klass->name;
9802                 /* trick to get relative numbering right when compiling corlib */
9803                 klass->name = "BuildingObject";
9804                 mono_class_setup_parent (klass, mono_defaults.object_class);
9805                 klass->name = old_n;
9806         }
9807
9808         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9809                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9810                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9811                 klass->instance_size = sizeof (MonoObject);
9812                 klass->size_inited = 1;
9813                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9814         }
9815
9816         mono_class_setup_mono_type (klass);
9817
9818         mono_class_setup_supertypes (klass);
9819
9820         /*
9821          * FIXME: handle interfaces.
9822          */
9823
9824         tb->type.type = &klass->byval_arg;
9825
9826         if (tb->nesting_type) {
9827                 g_assert (tb->nesting_type->type);
9828                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9829         }
9830
9831         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9832
9833         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9834         
9835         mono_loader_unlock ();
9836         return;
9837
9838 failure:
9839         mono_loader_unlock ();
9840         mono_error_raise_exception (&error);
9841 }
9842
9843 /*
9844  * mono_reflection_setup_generic_class:
9845  * @tb: a TypeBuilder object
9846  *
9847  * Setup the generic class before adding the first generic parameter.
9848  */
9849 void
9850 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9851 {
9852 }
9853
9854 /*
9855  * mono_reflection_create_generic_class:
9856  * @tb: a TypeBuilder object
9857  *
9858  * Creates the generic class after all generic parameters have been added.
9859  */
9860 void
9861 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9862 {
9863         MonoClass *klass;
9864         int count, i;
9865
9866         MONO_ARCH_SAVE_REGS;
9867
9868         klass = mono_class_from_mono_type (tb->type.type);
9869
9870         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9871
9872         if (klass->generic_container || (count == 0))
9873                 return;
9874
9875         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9876
9877         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9878
9879         klass->generic_container->owner.klass = klass;
9880         klass->generic_container->type_argc = count;
9881         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9882
9883         klass->is_generic = 1;
9884
9885         for (i = 0; i < count; i++) {
9886                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9887                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9888                 klass->generic_container->type_params [i] = *param;
9889                 /*Make sure we are a diferent type instance */
9890                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9891                 klass->generic_container->type_params [i].info.pklass = NULL;
9892                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9893
9894                 g_assert (klass->generic_container->type_params [i].param.owner);
9895         }
9896
9897         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9898 }
9899
9900 /*
9901  * mono_reflection_create_internal_class:
9902  * @tb: a TypeBuilder object
9903  *
9904  * Actually create the MonoClass that is associated with the TypeBuilder.
9905  */
9906 void
9907 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9908 {
9909         MonoClass *klass;
9910
9911         MONO_ARCH_SAVE_REGS;
9912
9913         klass = mono_class_from_mono_type (tb->type.type);
9914
9915         mono_loader_lock ();
9916         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9917                 MonoReflectionFieldBuilder *fb;
9918                 MonoClass *ec;
9919                 MonoType *enum_basetype;
9920
9921                 g_assert (tb->fields != NULL);
9922                 g_assert (mono_array_length (tb->fields) >= 1);
9923
9924                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9925
9926                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9927                         mono_loader_unlock ();
9928                         return;
9929                 }
9930
9931                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9932                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9933                 if (!klass->element_class)
9934                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9935
9936                 /*
9937                  * get the element_class from the current corlib.
9938                  */
9939                 ec = default_class_from_mono_type (enum_basetype);
9940                 klass->instance_size = ec->instance_size;
9941                 klass->size_inited = 1;
9942                 /* 
9943                  * this is almost safe to do with enums and it's needed to be able
9944                  * to create objects of the enum type (for use in SetConstant).
9945                  */
9946                 /* FIXME: Does this mean enums can't have method overrides ? */
9947                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9948         }
9949         mono_loader_unlock ();
9950 }
9951
9952 static MonoMarshalSpec*
9953 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9954                                                                 MonoReflectionMarshal *minfo)
9955 {
9956         MonoMarshalSpec *res;
9957
9958         res = image_g_new0 (image, MonoMarshalSpec, 1);
9959         res->native = minfo->type;
9960
9961         switch (minfo->type) {
9962         case MONO_NATIVE_LPARRAY:
9963                 res->data.array_data.elem_type = minfo->eltype;
9964                 if (minfo->has_size) {
9965                         res->data.array_data.param_num = minfo->param_num;
9966                         res->data.array_data.num_elem = minfo->count;
9967                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9968                 }
9969                 else {
9970                         res->data.array_data.param_num = -1;
9971                         res->data.array_data.num_elem = -1;
9972                         res->data.array_data.elem_mult = -1;
9973                 }
9974                 break;
9975
9976         case MONO_NATIVE_BYVALTSTR:
9977         case MONO_NATIVE_BYVALARRAY:
9978                 res->data.array_data.num_elem = minfo->count;
9979                 break;
9980
9981         case MONO_NATIVE_CUSTOM:
9982                 if (minfo->marshaltyperef)
9983                         res->data.custom_data.custom_name =
9984                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9985                 if (minfo->mcookie)
9986                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9987                 break;
9988
9989         default:
9990                 break;
9991         }
9992
9993         return res;
9994 }
9995 #endif /* !DISABLE_REFLECTION_EMIT */
9996
9997 MonoReflectionMarshalAsAttribute*
9998 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9999                                                                                    MonoMarshalSpec *spec)
10000 {
10001         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10002         MonoReflectionMarshalAsAttribute *minfo;
10003         MonoType *mtype;
10004
10005         if (!System_Reflection_Emit_MarshalAsAttribute) {
10006                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10007                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10008                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10009         }
10010
10011         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10012         minfo->utype = spec->native;
10013
10014         switch (minfo->utype) {
10015         case MONO_NATIVE_LPARRAY:
10016                 minfo->array_subtype = spec->data.array_data.elem_type;
10017                 minfo->size_const = spec->data.array_data.num_elem;
10018                 if (spec->data.array_data.param_num != -1)
10019                         minfo->size_param_index = spec->data.array_data.param_num;
10020                 break;
10021
10022         case MONO_NATIVE_BYVALTSTR:
10023         case MONO_NATIVE_BYVALARRAY:
10024                 minfo->size_const = spec->data.array_data.num_elem;
10025                 break;
10026
10027         case MONO_NATIVE_CUSTOM:
10028                 if (spec->data.custom_data.custom_name) {
10029                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10030                         if (mtype)
10031                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10032
10033                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10034                 }
10035                 if (spec->data.custom_data.cookie)
10036                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10037                 break;
10038
10039         default:
10040                 break;
10041         }
10042
10043         return minfo;
10044 }
10045
10046 #ifndef DISABLE_REFLECTION_EMIT
10047 static MonoMethod*
10048 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10049                                          ReflectionMethodBuilder *rmb,
10050                                          MonoMethodSignature *sig)
10051 {
10052         MonoError error;
10053         MonoMethod *m;
10054         MonoMethodWrapper *wrapperm;
10055         MonoMarshalSpec **specs;
10056         MonoReflectionMethodAux *method_aux;
10057         MonoImage *image;
10058         gboolean dynamic;
10059         int i;
10060
10061         mono_error_init (&error);
10062         /*
10063          * Methods created using a MethodBuilder should have their memory allocated
10064          * inside the image mempool, while dynamic methods should have their memory
10065          * malloc'd.
10066          */
10067         dynamic = rmb->refs != NULL;
10068         image = dynamic ? NULL : klass->image;
10069
10070         if (!dynamic)
10071                 g_assert (!klass->generic_class);
10072
10073         mono_loader_lock ();
10074
10075         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10076                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10077                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10078         else
10079                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10080
10081         wrapperm = (MonoMethodWrapper*)m;
10082
10083         m->dynamic = dynamic;
10084         m->slot = -1;
10085         m->flags = rmb->attrs;
10086         m->iflags = rmb->iattrs;
10087         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10088         m->klass = klass;
10089         m->signature = sig;
10090         m->sre_method = TRUE;
10091         m->skip_visibility = rmb->skip_visibility;
10092         if (rmb->table_idx)
10093                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10094
10095         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10096                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10097                         m->string_ctor = 1;
10098
10099                 m->signature->pinvoke = 1;
10100         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10101                 m->signature->pinvoke = 1;
10102
10103                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10104
10105                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10106                 g_assert (mono_error_ok (&error));
10107                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10108                 g_assert (mono_error_ok (&error));
10109                 
10110                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10111
10112                 if (klass->image->dynamic)
10113                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10114
10115                 mono_loader_unlock ();
10116
10117                 return m;
10118         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10119                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10120                 MonoMethodHeader *header;
10121                 guint32 code_size;
10122                 gint32 max_stack, i;
10123                 gint32 num_locals = 0;
10124                 gint32 num_clauses = 0;
10125                 guint8 *code;
10126
10127                 if (rmb->ilgen) {
10128                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10129                         code_size = rmb->ilgen->code_len;
10130                         max_stack = rmb->ilgen->max_stack;
10131                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10132                         if (rmb->ilgen->ex_handlers)
10133                                 num_clauses = method_count_clauses (rmb->ilgen);
10134                 } else {
10135                         if (rmb->code) {
10136                                 code = mono_array_addr (rmb->code, guint8, 0);
10137                                 code_size = mono_array_length (rmb->code);
10138                                 /* we probably need to run a verifier on the code... */
10139                                 max_stack = 8; 
10140                         }
10141                         else {
10142                                 code = NULL;
10143                                 code_size = 0;
10144                                 max_stack = 8;
10145                         }
10146                 }
10147
10148                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10149                 header->code_size = code_size;
10150                 header->code = image_g_malloc (image, code_size);
10151                 memcpy ((char*)header->code, code, code_size);
10152                 header->max_stack = max_stack;
10153                 header->init_locals = rmb->init_locals;
10154                 header->num_locals = num_locals;
10155
10156                 for (i = 0; i < num_locals; ++i) {
10157                         MonoReflectionLocalBuilder *lb = 
10158                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10159
10160                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10161                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10162                 }
10163
10164                 header->num_clauses = num_clauses;
10165                 if (num_clauses) {
10166                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10167                                  rmb->ilgen, num_clauses);
10168                 }
10169
10170                 wrapperm->header = header;
10171         }
10172
10173         if (rmb->generic_params) {
10174                 int count = mono_array_length (rmb->generic_params);
10175                 MonoGenericContainer *container = rmb->generic_container;
10176
10177                 g_assert (container);
10178
10179                 container->type_argc = count;
10180                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10181                 container->owner.method = m;
10182
10183                 m->is_generic = TRUE;
10184                 mono_method_set_generic_container (m, container);
10185
10186                 for (i = 0; i < count; i++) {
10187                         MonoReflectionGenericParam *gp =
10188                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10189                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10190                         container->type_params [i] = *param;
10191                 }
10192
10193                 /*
10194                  * The method signature might have pointers to generic parameters that belong to other methods.
10195                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10196                  * generic parameters.
10197                  */
10198                 for (i = 0; i < m->signature->param_count; ++i) {
10199                         MonoType *t = m->signature->params [i];
10200                         if (t->type == MONO_TYPE_MVAR) {
10201                                 MonoGenericParam *gparam =  t->data.generic_param;
10202                                 if (gparam->num < count) {
10203                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10204                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10205                                 }
10206
10207                         }
10208                 }
10209
10210                 if (klass->generic_container) {
10211                         container->parent = klass->generic_container;
10212                         container->context.class_inst = klass->generic_container->context.class_inst;
10213                 }
10214                 container->context.method_inst = mono_get_shared_generic_inst (container);
10215         }
10216
10217         if (rmb->refs) {
10218                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10219                 int i;
10220                 void **data;
10221
10222                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10223
10224                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10225                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10226                 for (i = 0; i < rmb->nrefs; ++i)
10227                         data [i + 1] = rmb->refs [i];
10228         }
10229
10230         method_aux = NULL;
10231
10232         /* Parameter info */
10233         if (rmb->pinfo) {
10234                 if (!method_aux)
10235                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10236                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10237                 for (i = 0; i <= m->signature->param_count; ++i) {
10238                         MonoReflectionParamBuilder *pb;
10239                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10240                                 if ((i > 0) && (pb->attrs)) {
10241                                         /* Make a copy since it might point to a shared type structure */
10242                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10243                                         m->signature->params [i - 1]->attrs = pb->attrs;
10244                                 }
10245
10246                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10247                                         MonoDynamicImage *assembly;
10248                                         guint32 idx, def_type, len;
10249                                         char *p;
10250                                         const char *p2;
10251
10252                                         if (!method_aux->param_defaults) {
10253                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10254                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10255                                         }
10256                                         assembly = (MonoDynamicImage*)klass->image;
10257                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10258                                         /* Copy the data from the blob since it might get realloc-ed */
10259                                         p = assembly->blob.data + idx;
10260                                         len = mono_metadata_decode_blob_size (p, &p2);
10261                                         len += p2 - p;
10262                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10263                                         method_aux->param_default_types [i] = def_type;
10264                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10265                                 }
10266
10267                                 if (pb->name) {
10268                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10269                                         g_assert (mono_error_ok (&error));
10270                                 }
10271                                 if (pb->cattrs) {
10272                                         if (!method_aux->param_cattr)
10273                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10274                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10275                                 }
10276                         }
10277                 }
10278         }
10279
10280         /* Parameter marshalling */
10281         specs = NULL;
10282         if (rmb->pinfo)         
10283                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10284                         MonoReflectionParamBuilder *pb;
10285                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10286                                 if (pb->marshal_info) {
10287                                         if (specs == NULL)
10288                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10289                                         specs [pb->position] = 
10290                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10291                                 }
10292                         }
10293                 }
10294         if (specs != NULL) {
10295                 if (!method_aux)
10296                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10297                 method_aux->param_marshall = specs;
10298         }
10299
10300         if (klass->image->dynamic && method_aux)
10301                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10302
10303         mono_loader_unlock ();
10304
10305         return m;
10306 }       
10307
10308 static MonoMethod*
10309 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10310 {
10311         ReflectionMethodBuilder rmb;
10312         MonoMethodSignature *sig;
10313
10314         mono_loader_lock ();
10315         sig = ctor_builder_to_signature (klass->image, mb);
10316         mono_loader_unlock ();
10317
10318         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10319
10320         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10321         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10322
10323         /* If we are in a generic class, we might be called multiple times from inflate_method */
10324         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10325                 /* ilgen is no longer needed */
10326                 mb->ilgen = NULL;
10327         }
10328
10329         return mb->mhandle;
10330 }
10331
10332 static MonoMethod*
10333 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10334 {
10335         ReflectionMethodBuilder rmb;
10336         MonoMethodSignature *sig;
10337
10338         mono_loader_lock ();
10339         sig = method_builder_to_signature (klass->image, mb);
10340         mono_loader_unlock ();
10341
10342         reflection_methodbuilder_from_method_builder (&rmb, mb);
10343
10344         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10345         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10346
10347         /* If we are in a generic class, we might be called multiple times from inflate_method */
10348         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10349                 /* ilgen is no longer needed */
10350                 mb->ilgen = NULL;
10351         }
10352         return mb->mhandle;
10353 }
10354
10355 static MonoClassField*
10356 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10357 {
10358         MonoClassField *field;
10359         MonoType *custom;
10360         MonoError error;
10361
10362         field = g_new0 (MonoClassField, 1);
10363
10364         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10365         g_assert (mono_error_ok (&error));
10366         if (fb->attrs || fb->modreq || fb->modopt) {
10367                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10368                 field->type->attrs = fb->attrs;
10369
10370                 g_assert (klass->image->dynamic);
10371                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10372                 g_free (field->type);
10373                 field->type = mono_metadata_type_dup (klass->image, custom);
10374                 g_free (custom);
10375         } else {
10376                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10377         }
10378         if (fb->offset != -1)
10379                 field->offset = fb->offset;
10380         field->parent = klass;
10381         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10382
10383         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10384
10385         return field;
10386 }
10387 #endif
10388
10389 MonoType*
10390 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10391 {
10392         MonoClass *klass;
10393         MonoReflectionTypeBuilder *tb = NULL;
10394         gboolean is_dynamic = FALSE;
10395         MonoDomain *domain;
10396         MonoClass *geninst;
10397
10398         mono_loader_lock ();
10399
10400         domain = mono_object_domain (type);
10401
10402         if (is_sre_type_builder (mono_object_class (type))) {
10403                 tb = (MonoReflectionTypeBuilder *) type;
10404
10405                 is_dynamic = TRUE;
10406         } else if (is_sre_generic_instance (mono_object_class (type))) {
10407                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10408                 MonoReflectionType *gtd = rgi->generic_type;
10409
10410                 if (is_sre_type_builder (mono_object_class (gtd))) {
10411                         tb = (MonoReflectionTypeBuilder *)gtd;
10412                         is_dynamic = TRUE;
10413                 }
10414         }
10415
10416         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10417         if (tb && tb->generic_container)
10418                 mono_reflection_create_generic_class (tb);
10419
10420         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10421         if (!klass->generic_container) {
10422                 mono_loader_unlock ();
10423                 return NULL;
10424         }
10425
10426         if (klass->wastypebuilder) {
10427                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10428
10429                 is_dynamic = TRUE;
10430         }
10431
10432         mono_loader_unlock ();
10433
10434         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10435
10436         return &geninst->byval_arg;
10437 }
10438
10439 MonoClass*
10440 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10441 {
10442         MonoGenericClass *gclass;
10443         MonoGenericInst *inst;
10444
10445         g_assert (klass->generic_container);
10446
10447         inst = mono_metadata_get_generic_inst (type_argc, types);
10448         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10449
10450         return mono_generic_class_get_class (gclass);
10451 }
10452
10453 MonoReflectionMethod*
10454 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10455 {
10456         MonoClass *klass;
10457         MonoMethod *method, *inflated;
10458         MonoMethodInflated *imethod;
10459         MonoGenericContext tmp_context;
10460         MonoGenericInst *ginst;
10461         MonoType **type_argv;
10462         int count, i;
10463
10464         MONO_ARCH_SAVE_REGS;
10465
10466         /*FIXME but this no longer should happen*/
10467         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10468 #ifndef DISABLE_REFLECTION_EMIT
10469                 MonoReflectionMethodBuilder *mb = NULL;
10470                 MonoReflectionTypeBuilder *tb;
10471                 MonoClass *klass;
10472
10473                 mb = (MonoReflectionMethodBuilder *) rmethod;
10474                 tb = (MonoReflectionTypeBuilder *) mb->type;
10475                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10476
10477                 method = methodbuilder_to_mono_method (klass, mb);
10478 #else
10479                 g_assert_not_reached ();
10480                 method = NULL;
10481 #endif
10482         } else {
10483                 method = rmethod->method;
10484         }
10485
10486         klass = method->klass;
10487
10488         if (method->is_inflated)
10489                 method = ((MonoMethodInflated *) method)->declaring;
10490
10491         count = mono_method_signature (method)->generic_param_count;
10492         if (count != mono_array_length (types))
10493                 return NULL;
10494
10495         type_argv = g_new0 (MonoType *, count);
10496         for (i = 0; i < count; i++) {
10497                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10498                 type_argv [i] = mono_reflection_type_get_handle (garg);
10499         }
10500         ginst = mono_metadata_get_generic_inst (count, type_argv);
10501         g_free (type_argv);
10502
10503         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10504         tmp_context.method_inst = ginst;
10505
10506         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10507         imethod = (MonoMethodInflated *) inflated;
10508
10509         /*FIXME but I think this is no longer necessary*/
10510         if (method->klass->image->dynamic) {
10511                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10512                 /*
10513                  * This table maps metadata structures representing inflated methods/fields
10514                  * to the reflection objects representing their generic definitions.
10515                  */
10516                 mono_loader_lock ();
10517                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10518                 mono_loader_unlock ();
10519         }
10520
10521         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10522                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10523         
10524         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10525 }
10526
10527 #ifndef DISABLE_REFLECTION_EMIT
10528
10529 static MonoMethod *
10530 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10531 {
10532         MonoMethodInflated *imethod;
10533         MonoGenericContext *context;
10534         int i;
10535
10536         /*
10537          * With generic code sharing the klass might not be inflated.
10538          * This can happen because classes inflated with their own
10539          * type arguments are "normalized" to the uninflated class.
10540          */
10541         if (!klass->generic_class)
10542                 return method;
10543
10544         context = mono_class_get_context (klass);
10545
10546         if (klass->method.count && klass->methods) {
10547                 /* Find the already created inflated method */
10548                 for (i = 0; i < klass->method.count; ++i) {
10549                         g_assert (klass->methods [i]->is_inflated);
10550                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10551                                 break;
10552                 }
10553                 g_assert (i < klass->method.count);
10554                 imethod = (MonoMethodInflated*)klass->methods [i];
10555         } else {
10556                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10557         }
10558
10559         if (method->is_generic && method->klass->image->dynamic) {
10560                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10561
10562                 mono_loader_lock ();
10563                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10564                 mono_loader_unlock ();
10565         }
10566         return (MonoMethod *) imethod;
10567 }
10568
10569 static MonoMethod *
10570 inflate_method (MonoReflectionType *type, MonoObject *obj)
10571 {
10572         MonoMethod *method;
10573         MonoClass *gklass;
10574
10575         MonoClass *type_class = mono_object_class (type);
10576
10577         if (is_sre_generic_instance (type_class)) {
10578                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10579                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10580         } else if (is_sre_type_builder (type_class)) {
10581                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10582         } else if (type->type) {
10583                 gklass = mono_class_from_mono_type (type->type);
10584                 gklass = mono_class_get_generic_type_definition (gklass);
10585         } else {
10586                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10587         }
10588
10589         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10590                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10591                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10592                 else
10593                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10594         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10595                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10596         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10597                 method = ((MonoReflectionMethod *) obj)->method;
10598         else {
10599                 method = NULL; /* prevent compiler warning */
10600                 g_error ("can't handle type %s", obj->vtable->klass->name);
10601         }
10602
10603         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10604 }
10605
10606 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10607 void
10608 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10609 {
10610         MonoGenericClass *gclass;
10611         MonoDynamicGenericClass *dgclass;
10612         MonoClass *klass, *gklass;
10613         MonoType *gtype;
10614         int i;
10615
10616         MONO_ARCH_SAVE_REGS;
10617
10618         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10619         klass = mono_class_from_mono_type (gtype);
10620         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10621         gclass = gtype->data.generic_class;
10622
10623         if (!gclass->is_dynamic)
10624                 return;
10625
10626         dgclass = (MonoDynamicGenericClass *) gclass;
10627
10628         if (dgclass->initialized)
10629                 return;
10630
10631         gklass = gclass->container_class;
10632         mono_class_init (gklass);
10633
10634         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10635
10636         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10637         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10638         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10639
10640         for (i = 0; i < dgclass->count_fields; i++) {
10641                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10642                 MonoClassField *field, *inflated_field = NULL;
10643
10644                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10645                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10646                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10647                         field = ((MonoReflectionField *) obj)->field;
10648                 else {
10649                         field = NULL; /* prevent compiler warning */
10650                         g_assert_not_reached ();
10651                 }
10652
10653                 dgclass->fields [i] = *field;
10654                 dgclass->fields [i].parent = klass;
10655                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10656                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10657                 dgclass->field_generic_types [i] = field->type;
10658                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10659                 dgclass->field_objects [i] = obj;
10660
10661                 if (inflated_field) {
10662                         g_free (inflated_field);
10663                 } else {
10664                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10665                 }
10666         }
10667
10668         dgclass->initialized = TRUE;
10669 }
10670
10671 void
10672 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10673 {
10674         MonoDynamicGenericClass *dgclass;
10675         int i;
10676
10677         g_assert (gclass->is_dynamic);
10678
10679         dgclass = (MonoDynamicGenericClass *)gclass;
10680
10681         for (i = 0; i < dgclass->count_fields; ++i) {
10682                 MonoClassField *field = dgclass->fields + i;
10683                 mono_metadata_free_type (field->type);
10684                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10685         }
10686 }
10687
10688 static void
10689 fix_partial_generic_class (MonoClass *klass)
10690 {
10691         MonoClass *gklass = klass->generic_class->container_class;
10692         MonoDynamicGenericClass *dgclass;
10693         int i;
10694
10695         if (klass->wastypebuilder)
10696                 return;
10697
10698         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10699         if (klass->parent != gklass->parent) {
10700                 MonoError error;
10701                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10702                 if (mono_error_ok (&error)) {
10703                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10704                         mono_metadata_free_type (parent_type);
10705                         if (parent != klass->parent) {
10706                                 /*fool mono_class_setup_parent*/
10707                                 klass->supertypes = NULL;
10708                                 mono_class_setup_parent (klass, parent);
10709                         }
10710                 } else {
10711                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10712                         mono_error_cleanup (&error);
10713                         if (gklass->wastypebuilder)
10714                                 klass->wastypebuilder = TRUE;
10715                         return;
10716                 }
10717         }
10718
10719         if (!dgclass->initialized)
10720                 return;
10721
10722         if (klass->method.count != gklass->method.count) {
10723                 klass->method.count = gklass->method.count;
10724                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10725
10726                 for (i = 0; i < klass->method.count; i++) {
10727                         klass->methods [i] = mono_class_inflate_generic_method_full (
10728                                 gklass->methods [i], klass, mono_class_get_context (klass));
10729                 }
10730         }
10731
10732         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10733                 klass->interface_count = gklass->interface_count;
10734                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10735                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10736
10737                 for (i = 0; i < gklass->interface_count; ++i) {
10738                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10739                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10740                         mono_metadata_free_type (iface_type);
10741
10742                         ensure_runtime_vtable (klass->interfaces [i]);
10743                 }
10744                 klass->interfaces_inited = 1;
10745         }
10746
10747         if (klass->field.count != gklass->field.count) {
10748                 klass->field.count = gklass->field.count;
10749                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10750
10751                 for (i = 0; i < klass->field.count; i++) {
10752                         klass->fields [i] = gklass->fields [i];
10753                         klass->fields [i].parent = klass;
10754                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10755                 }
10756         }
10757
10758         /*We can only finish with this klass once it's parent has as well*/
10759         if (gklass->wastypebuilder)
10760                 klass->wastypebuilder = TRUE;
10761         return;
10762 }
10763
10764 static void
10765 ensure_generic_class_runtime_vtable (MonoClass *klass)
10766 {
10767         MonoClass *gklass = klass->generic_class->container_class;
10768
10769         ensure_runtime_vtable (gklass); 
10770
10771         fix_partial_generic_class (klass);
10772 }
10773
10774 static void
10775 ensure_runtime_vtable (MonoClass *klass)
10776 {
10777         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10778         int i, num, j;
10779
10780         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10781                 return;
10782         if (klass->parent)
10783                 ensure_runtime_vtable (klass->parent);
10784
10785         if (tb) {
10786                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10787                 num += tb->num_methods;
10788                 klass->method.count = num;
10789                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10790                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10791                 for (i = 0; i < num; ++i)
10792                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10793                 num = tb->num_methods;
10794                 j = i;
10795                 for (i = 0; i < num; ++i)
10796                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10797         
10798                 if (tb->interfaces) {
10799                         klass->interface_count = mono_array_length (tb->interfaces);
10800                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10801                         for (i = 0; i < klass->interface_count; ++i) {
10802                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10803                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10804                                 ensure_runtime_vtable (klass->interfaces [i]);
10805                         }
10806                         klass->interfaces_inited = 1;
10807                 }
10808         } else if (klass->generic_class){
10809                 ensure_generic_class_runtime_vtable (klass);
10810         }
10811
10812         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10813                 int slot_num = 0;
10814                 for (i = 0; i < klass->method.count; ++i) {
10815                         MonoMethod *im = klass->methods [i];
10816                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10817                                 im->slot = slot_num++;
10818                 }
10819                 
10820                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10821                 mono_class_setup_interface_offsets (klass);
10822                 mono_class_setup_interface_id (klass);
10823         }
10824
10825         /*
10826          * The generic vtable is needed even if image->run is not set since some
10827          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10828          * method->slot being defined.
10829          */
10830
10831         /* 
10832          * tb->methods could not be freed since it is used for determining 
10833          * overrides during dynamic vtable construction.
10834          */
10835 }
10836
10837 static MonoMethod*
10838 mono_reflection_method_get_handle (MonoObject *method)
10839 {
10840         MonoClass *class = mono_object_class (method);
10841         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10842                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10843                 return sr_method->method;
10844         }
10845         if (is_sre_method_builder (class)) {
10846                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10847                 return mb->mhandle;
10848         }
10849         if (is_sre_method_on_tb_inst (class)) {
10850                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10851                 MonoMethod *result;
10852                 /*FIXME move this to a proper method and unify with resolve_object*/
10853                 if (m->method_args) {
10854                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10855                 } else {
10856                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10857                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10858                         MonoMethod *mono_method;
10859
10860                         if (is_sre_method_builder (mono_object_class (m->mb)))
10861                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10862                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10863                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10864                         else
10865                                 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)));
10866
10867                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10868                 }
10869                 return result;
10870         }
10871
10872         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10873         return NULL;
10874 }
10875
10876 void
10877 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10878 {
10879         MonoReflectionTypeBuilder *tb;
10880         int i, j, onum;
10881         MonoReflectionMethod *m;
10882
10883         *overrides = NULL;
10884         *num_overrides = 0;
10885
10886         g_assert (klass->image->dynamic);
10887
10888         if (!mono_class_get_ref_info (klass))
10889                 return;
10890
10891         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10892
10893         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10894
10895         onum = 0;
10896         if (tb->methods) {
10897                 for (i = 0; i < tb->num_methods; ++i) {
10898                         MonoReflectionMethodBuilder *mb = 
10899                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10900                         if (mb->override_methods)
10901                                 onum += mono_array_length (mb->override_methods);
10902                 }
10903         }
10904
10905         if (onum) {
10906                 *overrides = g_new0 (MonoMethod*, onum * 2);
10907
10908                 onum = 0;
10909                 for (i = 0; i < tb->num_methods; ++i) {
10910                         MonoReflectionMethodBuilder *mb = 
10911                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10912                         if (mb->override_methods) {
10913                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10914                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10915
10916                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10917                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10918
10919                                         g_assert (mb->mhandle);
10920
10921                                         onum ++;
10922                                 }
10923                         }
10924                 }
10925         }
10926
10927         *num_overrides = onum;
10928 }
10929
10930 static void
10931 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10932 {
10933         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10934         MonoReflectionFieldBuilder *fb;
10935         MonoClassField *field;
10936         MonoImage *image = klass->image;
10937         const char *p, *p2;
10938         int i;
10939         guint32 len, idx, real_size = 0;
10940
10941         klass->field.count = tb->num_fields;
10942         klass->field.first = 0;
10943
10944         mono_error_init (error);
10945
10946         if (tb->class_size) {
10947                 if ((tb->packing_size & 0xfffffff0) != 0) {
10948                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10949                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10950                         return;
10951                 }
10952                 klass->packing_size = tb->packing_size;
10953                 real_size = klass->instance_size + tb->class_size;
10954         }
10955
10956         if (!klass->field.count) {
10957                 klass->instance_size = MAX (klass->instance_size, real_size);
10958                 return;
10959         }
10960         
10961         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10962         mono_class_alloc_ext (klass);
10963         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10964         /*
10965         This is, guess what, a hack.
10966         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10967         On the static path no field class is resolved, only types are built. This is the right thing to do
10968         but we suck.
10969         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10970         */
10971         klass->size_inited = 1;
10972
10973         for (i = 0; i < klass->field.count; ++i) {
10974                 MonoArray *rva_data;
10975                 fb = mono_array_get (tb->fields, gpointer, i);
10976                 field = &klass->fields [i];
10977                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10978                 if (!mono_error_ok (error))
10979                         return;
10980                 if (fb->attrs) {
10981                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10982                         field->type->attrs = fb->attrs;
10983                 } else {
10984                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10985                 }
10986
10987                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
10988                         char *base = mono_array_addr (rva_data, char, 0);
10989                         size_t size = mono_array_length (rva_data);
10990                         char *data = mono_image_alloc (klass->image, size);
10991                         memcpy (data, base, size);
10992                         klass->ext->field_def_values [i].data = data;
10993                 }
10994                 if (fb->offset != -1)
10995                         field->offset = fb->offset;
10996                 field->parent = klass;
10997                 fb->handle = field;
10998                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10999
11000                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11001                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11002                 }
11003                 if (fb->def_value) {
11004                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11005                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11006                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11007                         /* Copy the data from the blob since it might get realloc-ed */
11008                         p = assembly->blob.data + idx;
11009                         len = mono_metadata_decode_blob_size (p, &p2);
11010                         len += p2 - p;
11011                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11012                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11013                 }
11014         }
11015
11016         klass->instance_size = MAX (klass->instance_size, real_size);
11017         mono_class_layout_fields (klass);
11018 }
11019
11020 static void
11021 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11022 {
11023         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11024         MonoReflectionPropertyBuilder *pb;
11025         MonoImage *image = klass->image;
11026         MonoProperty *properties;
11027         int i;
11028
11029         mono_error_init (error);
11030
11031         if (!klass->ext)
11032                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11033
11034         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11035         klass->ext->property.first = 0;
11036
11037         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11038         klass->ext->properties = properties;
11039         for (i = 0; i < klass->ext->property.count; ++i) {
11040                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11041                 properties [i].parent = klass;
11042                 properties [i].attrs = pb->attrs;
11043                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11044                 if (!mono_error_ok (error))
11045                         return;
11046                 if (pb->get_method)
11047                         properties [i].get = pb->get_method->mhandle;
11048                 if (pb->set_method)
11049                         properties [i].set = pb->set_method->mhandle;
11050
11051                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11052                 if (pb->def_value) {
11053                         guint32 len, idx;
11054                         const char *p, *p2;
11055                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11056                         if (!klass->ext->prop_def_values)
11057                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11058                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11059                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11060                         /* Copy the data from the blob since it might get realloc-ed */
11061                         p = assembly->blob.data + idx;
11062                         len = mono_metadata_decode_blob_size (p, &p2);
11063                         len += p2 - p;
11064                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11065                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11066                 }
11067         }
11068 }
11069
11070 MonoReflectionEvent *
11071 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11072 {
11073         MonoEvent *event = g_new0 (MonoEvent, 1);
11074         MonoClass *klass;
11075
11076         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11077
11078         event->parent = klass;
11079         event->attrs = eb->attrs;
11080         event->name = mono_string_to_utf8 (eb->name);
11081         if (eb->add_method)
11082                 event->add = eb->add_method->mhandle;
11083         if (eb->remove_method)
11084                 event->remove = eb->remove_method->mhandle;
11085         if (eb->raise_method)
11086                 event->raise = eb->raise_method->mhandle;
11087
11088 #ifndef MONO_SMALL_CONFIG
11089         if (eb->other_methods) {
11090                 int j;
11091                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11092                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11093                         MonoReflectionMethodBuilder *mb = 
11094                                 mono_array_get (eb->other_methods,
11095                                                 MonoReflectionMethodBuilder*, j);
11096                         event->other [j] = mb->mhandle;
11097                 }
11098         }
11099 #endif
11100
11101         return mono_event_get_object (mono_object_domain (tb), klass, event);
11102 }
11103
11104 static void
11105 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11106 {
11107         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11108         MonoReflectionEventBuilder *eb;
11109         MonoImage *image = klass->image;
11110         MonoEvent *events;
11111         int i;
11112
11113         mono_error_init (error);
11114
11115         if (!klass->ext)
11116                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11117
11118         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11119         klass->ext->event.first = 0;
11120
11121         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11122         klass->ext->events = events;
11123         for (i = 0; i < klass->ext->event.count; ++i) {
11124                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11125                 events [i].parent = klass;
11126                 events [i].attrs = eb->attrs;
11127                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11128                 if (!mono_error_ok (error))
11129                         return;
11130                 if (eb->add_method)
11131                         events [i].add = eb->add_method->mhandle;
11132                 if (eb->remove_method)
11133                         events [i].remove = eb->remove_method->mhandle;
11134                 if (eb->raise_method)
11135                         events [i].raise = eb->raise_method->mhandle;
11136
11137 #ifndef MONO_SMALL_CONFIG
11138                 if (eb->other_methods) {
11139                         int j;
11140                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11141                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11142                                 MonoReflectionMethodBuilder *mb = 
11143                                         mono_array_get (eb->other_methods,
11144                                                                         MonoReflectionMethodBuilder*, j);
11145                                 events [i].other [j] = mb->mhandle;
11146                         }
11147                 }
11148 #endif
11149                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11150         }
11151 }
11152
11153 static gboolean
11154 remove_instantiations_of_and_ensure_contents (gpointer key,
11155                                                   gpointer value,
11156                                                   gpointer user_data)
11157 {
11158         MonoType *type = (MonoType*)key;
11159         MonoClass *klass = (MonoClass*)user_data;
11160
11161         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11162                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11163                 return TRUE;
11164         } else
11165                 return FALSE;
11166 }
11167
11168 static void
11169 check_array_for_usertypes (MonoArray *arr)
11170 {
11171         int i;
11172
11173         if (!arr)
11174                 return;
11175
11176         for (i = 0; i < mono_array_length (arr); ++i)
11177                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11178 }
11179
11180 MonoReflectionType*
11181 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11182 {
11183         MonoError error;
11184         MonoClass *klass;
11185         MonoDomain* domain;
11186         MonoReflectionType* res;
11187         int i, j;
11188
11189         MONO_ARCH_SAVE_REGS;
11190
11191         domain = mono_object_domain (tb);
11192         klass = mono_class_from_mono_type (tb->type.type);
11193
11194         /*
11195          * Check for user defined Type subclasses.
11196          */
11197         RESOLVE_TYPE (tb->parent);
11198         check_array_for_usertypes (tb->interfaces);
11199         if (tb->fields) {
11200                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11201                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11202                         if (fb) {
11203                                 RESOLVE_TYPE (fb->type);
11204                                 check_array_for_usertypes (fb->modreq);
11205                                 check_array_for_usertypes (fb->modopt);
11206                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11207                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11208                         }
11209                 }
11210         }
11211         if (tb->methods) {
11212                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11213                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11214                         if (mb) {
11215                                 RESOLVE_TYPE (mb->rtype);
11216                                 check_array_for_usertypes (mb->return_modreq);
11217                                 check_array_for_usertypes (mb->return_modopt);
11218                                 check_array_for_usertypes (mb->parameters);
11219                                 if (mb->param_modreq)
11220                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11221                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11222                                 if (mb->param_modopt)
11223                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11224                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11225                         }
11226                 }
11227         }
11228         if (tb->ctors) {
11229                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11230                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11231                         if (mb) {
11232                                 check_array_for_usertypes (mb->parameters);
11233                                 if (mb->param_modreq)
11234                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11235                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11236                                 if (mb->param_modopt)
11237                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11238                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11239                         }
11240                 }
11241         }
11242
11243         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11244
11245         /* 
11246          * we need to lock the domain because the lock will be taken inside
11247          * So, we need to keep the locking order correct.
11248          */
11249         mono_loader_lock ();
11250         mono_domain_lock (domain);
11251         if (klass->wastypebuilder) {
11252                 mono_domain_unlock (domain);
11253                 mono_loader_unlock ();
11254                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11255         }
11256         /*
11257          * Fields to set in klass:
11258          * the various flags: delegate/unicode/contextbound etc.
11259          */
11260         klass->flags = tb->attrs;
11261         klass->has_cctor = 1;
11262         klass->has_finalize = 1;
11263         klass->has_finalize_inited = 1;
11264
11265         /* fool mono_class_setup_parent */
11266         klass->supertypes = NULL;
11267         mono_class_setup_parent (klass, klass->parent);
11268         mono_class_setup_mono_type (klass);
11269
11270 #if 0
11271         if (!((MonoDynamicImage*)klass->image)->run) {
11272                 if (klass->generic_container) {
11273                         /* FIXME: The code below can't handle generic classes */
11274                         klass->wastypebuilder = TRUE;
11275                         mono_loader_unlock ();
11276                         mono_domain_unlock (domain);
11277                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11278                 }
11279         }
11280 #endif
11281
11282         /* enums are done right away */
11283         if (!klass->enumtype)
11284                 ensure_runtime_vtable (klass);
11285
11286         if (tb->subtypes) {
11287                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11288                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11289                         mono_class_alloc_ext (klass);
11290                         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)));
11291                 }
11292         }
11293
11294         klass->nested_classes_inited = TRUE;
11295
11296         /* fields and object layout */
11297         if (klass->parent) {
11298                 if (!klass->parent->size_inited)
11299                         mono_class_init (klass->parent);
11300                 klass->instance_size = klass->parent->instance_size;
11301                 klass->sizes.class_size = 0;
11302                 klass->min_align = klass->parent->min_align;
11303                 /* if the type has no fields we won't call the field_setup
11304                  * routine which sets up klass->has_references.
11305                  */
11306                 klass->has_references |= klass->parent->has_references;
11307         } else {
11308                 klass->instance_size = sizeof (MonoObject);
11309                 klass->min_align = 1;
11310         }
11311
11312         /* FIXME: handle packing_size and instance_size */
11313         typebuilder_setup_fields (klass, &error);
11314         if (!mono_error_ok (&error))
11315                 goto failure;
11316         typebuilder_setup_properties (klass, &error);
11317         if (!mono_error_ok (&error))
11318                 goto failure;
11319
11320         typebuilder_setup_events (klass, &error);
11321         if (!mono_error_ok (&error))
11322                 goto failure;
11323
11324         klass->wastypebuilder = TRUE;
11325
11326         /* 
11327          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11328          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11329          * we want to return normal System.MonoType objects, so clear these out from the cache.
11330          *
11331          * Together with this we must ensure the contents of all instances to match the created type.
11332          */
11333         if (domain->type_hash && klass->generic_container)
11334                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11335
11336         mono_domain_unlock (domain);
11337         mono_loader_unlock ();
11338
11339         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11340                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11341                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11342         }
11343
11344         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11345         g_assert (res != (MonoReflectionType*)tb);
11346
11347         return res;
11348
11349 failure:
11350         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11351         klass->wastypebuilder = TRUE;
11352         mono_domain_unlock (domain);
11353         mono_loader_unlock ();
11354         mono_error_raise_exception (&error);
11355         return NULL;
11356 }
11357
11358 void
11359 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11360 {
11361         MonoGenericParamFull *param;
11362         MonoImage *image;
11363         MonoClass *pklass;
11364         MonoError error;
11365
11366         MONO_ARCH_SAVE_REGS;
11367
11368         image = &gparam->tbuilder->module->dynamic_image->image;
11369
11370         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11371
11372         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11373         g_assert (mono_error_ok (&error));
11374         param->param.num = gparam->index;
11375
11376         if (gparam->mbuilder) {
11377                 if (!gparam->mbuilder->generic_container) {
11378                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11379                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11380                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11381                         gparam->mbuilder->generic_container->is_method = TRUE;
11382                         /* 
11383                          * Cannot set owner.method, since the MonoMethod is not created yet.
11384                          * Set the image field instead, so type_in_image () works.
11385                          */
11386                         gparam->mbuilder->generic_container->image = klass->image;
11387                 }
11388                 param->param.owner = gparam->mbuilder->generic_container;
11389         } else if (gparam->tbuilder) {
11390                 if (!gparam->tbuilder->generic_container) {
11391                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11392                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11393                         gparam->tbuilder->generic_container->owner.klass = klass;
11394                 }
11395                 param->param.owner = gparam->tbuilder->generic_container;
11396         }
11397
11398         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11399
11400         gparam->type.type = &pklass->byval_arg;
11401
11402         mono_class_set_ref_info (pklass, gparam);
11403         mono_image_lock (image);
11404         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11405         mono_image_unlock (image);
11406 }
11407
11408 MonoArray *
11409 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11410 {
11411         MonoReflectionModuleBuilder *module = sig->module;
11412         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11413         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11414         guint32 buflen, i;
11415         MonoArray *result;
11416         SigBuffer buf;
11417
11418         check_array_for_usertypes (sig->arguments);
11419
11420         sigbuffer_init (&buf, 32);
11421
11422         sigbuffer_add_value (&buf, 0x07);
11423         sigbuffer_add_value (&buf, na);
11424         if (assembly != NULL){
11425                 for (i = 0; i < na; ++i) {
11426                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11427                         encode_reflection_type (assembly, type, &buf);
11428                 }
11429         }
11430
11431         buflen = buf.p - buf.buf;
11432         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11433         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11434         sigbuffer_free (&buf);
11435
11436         return result;
11437 }
11438
11439 MonoArray *
11440 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11441 {
11442         MonoDynamicImage *assembly = sig->module->dynamic_image;
11443         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11444         guint32 buflen, i;
11445         MonoArray *result;
11446         SigBuffer buf;
11447
11448         check_array_for_usertypes (sig->arguments);
11449
11450         sigbuffer_init (&buf, 32);
11451
11452         sigbuffer_add_value (&buf, 0x06);
11453         for (i = 0; i < na; ++i) {
11454                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11455                 encode_reflection_type (assembly, type, &buf);
11456         }
11457
11458         buflen = buf.p - buf.buf;
11459         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11460         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11461         sigbuffer_free (&buf);
11462
11463         return result;
11464 }
11465
11466 typedef struct {
11467         MonoMethod *handle;
11468         MonoDomain *domain;
11469 } DynamicMethodReleaseData;
11470
11471 /*
11472  * The runtime automatically clean up those after finalization.
11473 */      
11474 static MonoReferenceQueue *dynamic_method_queue;
11475
11476 static void
11477 free_dynamic_method (void *dynamic_method)
11478 {
11479         DynamicMethodReleaseData *data = dynamic_method;
11480
11481         mono_runtime_free_method (data->domain, data->handle);
11482         g_free (data);
11483 }
11484
11485 void 
11486 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11487 {
11488         MonoReferenceQueue *queue;
11489         MonoMethod *handle;
11490         DynamicMethodReleaseData *release_data;
11491         ReflectionMethodBuilder rmb;
11492         MonoMethodSignature *sig;
11493         MonoClass *klass;
11494         GSList *l;
11495         int i;
11496
11497         if (mono_runtime_is_shutting_down ())
11498                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11499
11500         if (!(queue = dynamic_method_queue)) {
11501                 mono_loader_lock ();
11502                 if (!(queue = dynamic_method_queue))
11503                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11504                 mono_loader_unlock ();
11505         }
11506
11507         sig = dynamic_method_to_signature (mb);
11508
11509         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11510
11511         /*
11512          * Resolve references.
11513          */
11514         /* 
11515          * Every second entry in the refs array is reserved for storing handle_class,
11516          * which is needed by the ldtoken implementation in the JIT.
11517          */
11518         rmb.nrefs = mb->nrefs;
11519         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11520         for (i = 0; i < mb->nrefs; i += 2) {
11521                 MonoClass *handle_class;
11522                 gpointer ref;
11523                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11524
11525                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11526                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11527                         /*
11528                          * The referenced DynamicMethod should already be created by the managed
11529                          * code, except in the case of circular references. In that case, we store
11530                          * method in the refs array, and fix it up later when the referenced 
11531                          * DynamicMethod is created.
11532                          */
11533                         if (method->mhandle) {
11534                                 ref = method->mhandle;
11535                         } else {
11536                                 /* FIXME: GC object stored in unmanaged memory */
11537                                 ref = method;
11538
11539                                 /* FIXME: GC object stored in unmanaged memory */
11540                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11541                         }
11542                         handle_class = mono_defaults.methodhandle_class;
11543                 } else {
11544                         MonoException *ex = NULL;
11545                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11546                         if (!ref)
11547                                 ex = mono_get_exception_type_load (NULL, NULL);
11548                         else if (mono_security_core_clr_enabled ())
11549                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11550
11551                         if (ex) {
11552                                 g_free (rmb.refs);
11553                                 mono_raise_exception (ex);
11554                                 return;
11555                         }
11556                 }
11557
11558                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11559                 rmb.refs [i + 1] = handle_class;
11560         }               
11561
11562         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11563
11564         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11565         release_data = g_new (DynamicMethodReleaseData, 1);
11566         release_data->handle = handle;
11567         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11568         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11569                 g_free (release_data);
11570
11571         /* Fix up refs entries pointing at us */
11572         for (l = mb->referenced_by; l; l = l->next) {
11573                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11574                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11575                 gpointer *data;
11576                 
11577                 g_assert (method->mhandle);
11578
11579                 data = (gpointer*)wrapper->method_data;
11580                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11581                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11582                                 data [i + 1] = mb->mhandle;
11583                 }
11584         }
11585         g_slist_free (mb->referenced_by);
11586
11587         g_free (rmb.refs);
11588
11589         /* ilgen is no longer needed */
11590         mb->ilgen = NULL;
11591 }
11592
11593 #endif /* DISABLE_REFLECTION_EMIT */
11594
11595 /**
11596  * 
11597  * mono_reflection_is_valid_dynamic_token:
11598  * 
11599  * Returns TRUE if token is valid.
11600  * 
11601  */
11602 gboolean
11603 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11604 {
11605         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11606 }
11607
11608 MonoMethodSignature *
11609 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11610 {
11611         MonoMethodSignature *sig;
11612         g_assert (image->dynamic);
11613
11614         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11615         if (sig)
11616                 return sig;
11617
11618         return mono_method_signature (method);
11619 }
11620
11621 #ifndef DISABLE_REFLECTION_EMIT
11622
11623 /**
11624  * mono_reflection_lookup_dynamic_token:
11625  *
11626  * Finish the Builder object pointed to by TOKEN and return the corresponding
11627  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11628  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11629  * mapping table.
11630  *
11631  * LOCKING: Take the loader lock
11632  */
11633 gpointer
11634 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11635 {
11636         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11637         MonoObject *obj;
11638         MonoClass *klass;
11639
11640         mono_loader_lock ();
11641         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11642         mono_loader_unlock ();
11643         if (!obj) {
11644                 if (valid_token)
11645                         g_error ("Could not find required dynamic token 0x%08x", token);
11646                 else
11647                         return NULL;
11648         }
11649
11650         if (!handle_class)
11651                 handle_class = &klass;
11652         return resolve_object (image, obj, handle_class, context);
11653 }
11654
11655 /*
11656  * ensure_complete_type:
11657  *
11658  *   Ensure that KLASS is completed if it is a dynamic type, or references
11659  * dynamic types.
11660  */
11661 static void
11662 ensure_complete_type (MonoClass *klass)
11663 {
11664         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11665                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11666
11667                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11668
11669                 // Asserting here could break a lot of code
11670                 //g_assert (klass->wastypebuilder);
11671         }
11672
11673         if (klass->generic_class) {
11674                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11675                 int i;
11676
11677                 for (i = 0; i < inst->type_argc; ++i) {
11678                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11679                 }
11680         }
11681 }
11682
11683 static gpointer
11684 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11685 {
11686         gpointer result = NULL;
11687
11688         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11689                 result = mono_string_intern ((MonoString*)obj);
11690                 *handle_class = mono_defaults.string_class;
11691                 g_assert (result);
11692         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11693                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11694                 MonoClass *mc = mono_class_from_mono_type (type);
11695                 if (!mono_class_init (mc))
11696                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11697
11698                 if (context) {
11699                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11700                         result = mono_class_from_mono_type (inflated);
11701                         mono_metadata_free_type (inflated);
11702                 } else {
11703                         result = mono_class_from_mono_type (type);
11704                 }
11705                 *handle_class = mono_defaults.typehandle_class;
11706                 g_assert (result);
11707         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11708                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11709                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11710                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11711                 result = ((MonoReflectionMethod*)obj)->method;
11712                 if (context)
11713                         result = mono_class_inflate_generic_method (result, context);
11714                 *handle_class = mono_defaults.methodhandle_class;
11715                 g_assert (result);
11716         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11717                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11718                 result = mb->mhandle;
11719                 if (!result) {
11720                         /* Type is not yet created */
11721                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11722
11723                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11724
11725                         /*
11726                          * Hopefully this has been filled in by calling CreateType() on the
11727                          * TypeBuilder.
11728                          */
11729                         /*
11730                          * TODO: This won't work if the application finishes another 
11731                          * TypeBuilder instance instead of this one.
11732                          */
11733                         result = mb->mhandle;
11734                 }
11735                 if (context)
11736                         result = mono_class_inflate_generic_method (result, context);
11737                 *handle_class = mono_defaults.methodhandle_class;
11738         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11739                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11740
11741                 result = cb->mhandle;
11742                 if (!result) {
11743                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11744
11745                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11746                         result = cb->mhandle;
11747                 }
11748                 if (context)
11749                         result = mono_class_inflate_generic_method (result, context);
11750                 *handle_class = mono_defaults.methodhandle_class;
11751         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11752                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11753
11754                 ensure_complete_type (field->parent);
11755                 if (context) {
11756                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11757                         MonoClass *class = mono_class_from_mono_type (inflated);
11758                         MonoClassField *inflated_field;
11759                         gpointer iter = NULL;
11760                         mono_metadata_free_type (inflated);
11761                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11762                                 if (!strcmp (field->name, inflated_field->name))
11763                                         break;
11764                         }
11765                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11766                         result = inflated_field;
11767                 } else {
11768                         result = field;
11769                 }
11770                 *handle_class = mono_defaults.fieldhandle_class;
11771                 g_assert (result);
11772         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11773                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11774                 result = fb->handle;
11775
11776                 if (!result) {
11777                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11778
11779                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11780                         result = fb->handle;
11781                 }
11782
11783                 if (fb->handle && fb->handle->parent->generic_container) {
11784                         MonoClass *klass = fb->handle->parent;
11785                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11786                         MonoClass *inflated = mono_class_from_mono_type (type);
11787
11788                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11789                         g_assert (result);
11790                         mono_metadata_free_type (type);
11791                 }
11792                 *handle_class = mono_defaults.fieldhandle_class;
11793         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11794                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11795                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11796                 MonoClass *klass;
11797
11798                 klass = type->data.klass;
11799                 if (klass->wastypebuilder) {
11800                         /* Already created */
11801                         result = klass;
11802                 }
11803                 else {
11804                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11805                         result = type->data.klass;
11806                         g_assert (result);
11807                 }
11808                 *handle_class = mono_defaults.typehandle_class;
11809         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11810                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11811                 MonoMethodSignature *sig;
11812                 int nargs, i;
11813
11814                 if (helper->arguments)
11815                         nargs = mono_array_length (helper->arguments);
11816                 else
11817                         nargs = 0;
11818
11819                 sig = mono_metadata_signature_alloc (image, nargs);
11820                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11821                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11822
11823                 if (helper->unmanaged_call_conv) { /* unmanaged */
11824                         sig->call_convention = helper->unmanaged_call_conv - 1;
11825                         sig->pinvoke = TRUE;
11826                 } else if (helper->call_conv & 0x02) {
11827                         sig->call_convention = MONO_CALL_VARARG;
11828                 } else {
11829                         sig->call_convention = MONO_CALL_DEFAULT;
11830                 }
11831
11832                 sig->param_count = nargs;
11833                 /* TODO: Copy type ? */
11834                 sig->ret = helper->return_type->type;
11835                 for (i = 0; i < nargs; ++i)
11836                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11837
11838                 result = sig;
11839                 *handle_class = NULL;
11840         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11841                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11842                 /* Already created by the managed code */
11843                 g_assert (method->mhandle);
11844                 result = method->mhandle;
11845                 *handle_class = mono_defaults.methodhandle_class;
11846         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11847                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11848                 type = mono_class_inflate_generic_type (type, context);
11849                 result = mono_class_from_mono_type (type);
11850                 *handle_class = mono_defaults.typehandle_class;
11851                 g_assert (result);
11852                 mono_metadata_free_type (type);
11853         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11854                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11855                 type = mono_class_inflate_generic_type (type, context);
11856                 result = mono_class_from_mono_type (type);
11857                 *handle_class = mono_defaults.typehandle_class;
11858                 g_assert (result);
11859                 mono_metadata_free_type (type);
11860         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11861                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11862                 MonoClass *inflated;
11863                 MonoType *type;
11864                 MonoClassField *field;
11865
11866                 if (is_sre_field_builder (mono_object_class (f->fb)))
11867                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11868                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11869                         field = ((MonoReflectionField*)f->fb)->field;
11870                 else
11871                         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)));
11872
11873                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11874                 inflated = mono_class_from_mono_type (type);
11875
11876                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11877                 ensure_complete_type (field->parent);
11878                 g_assert (result);
11879                 mono_metadata_free_type (type);
11880                 *handle_class = mono_defaults.fieldhandle_class;
11881         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11882                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11883                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11884                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11885                 MonoMethod *method;
11886
11887                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11888                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11889                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11890                         method = ((MonoReflectionMethod *)c->cb)->method;
11891                 else
11892                         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)));
11893
11894                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11895                 *handle_class = mono_defaults.methodhandle_class;
11896                 mono_metadata_free_type (type);
11897         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11898                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11899                 if (m->method_args) {
11900                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11901                         if (context)
11902                                 result = mono_class_inflate_generic_method (result, context);
11903                 } else {
11904                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11905                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11906                         MonoMethod *method;
11907
11908                         if (is_sre_method_builder (mono_object_class (m->mb)))
11909                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11910                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11911                                 method = ((MonoReflectionMethod *)m->mb)->method;
11912                         else
11913                                 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)));
11914
11915                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11916                         mono_metadata_free_type (type);
11917                 }
11918                 *handle_class = mono_defaults.methodhandle_class;
11919         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11920                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11921                 MonoType *mtype;
11922                 MonoClass *klass;
11923                 MonoMethod *method;
11924                 gpointer iter;
11925                 char *name;
11926
11927                 mtype = mono_reflection_type_get_handle (m->parent);
11928                 klass = mono_class_from_mono_type (mtype);
11929
11930                 /* Find the method */
11931
11932                 name = mono_string_to_utf8 (m->name);
11933                 iter = NULL;
11934                 while ((method = mono_class_get_methods (klass, &iter))) {
11935                         if (!strcmp (method->name, name))
11936                                 break;
11937                 }
11938                 g_free (name);
11939
11940                 // FIXME:
11941                 g_assert (method);
11942                 // FIXME: Check parameters/return value etc. match
11943
11944                 result = method;
11945                 *handle_class = mono_defaults.methodhandle_class;
11946         } else if (is_sre_array (mono_object_get_class(obj)) ||
11947                                 is_sre_byref (mono_object_get_class(obj)) ||
11948                                 is_sre_pointer (mono_object_get_class(obj))) {
11949                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11950                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11951
11952                 if (context) {
11953                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11954                         result = mono_class_from_mono_type (inflated);
11955                         mono_metadata_free_type (inflated);
11956                 } else {
11957                         result = mono_class_from_mono_type (type);
11958                 }
11959                 *handle_class = mono_defaults.typehandle_class;
11960         } else {
11961                 g_print ("%s\n", obj->vtable->klass->name);
11962                 g_assert_not_reached ();
11963         }
11964         return result;
11965 }
11966
11967 #else /* DISABLE_REFLECTION_EMIT */
11968
11969 MonoArray*
11970 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11971 {
11972         g_assert_not_reached ();
11973         return NULL;
11974 }
11975
11976 void
11977 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11978 {
11979         g_assert_not_reached ();
11980 }
11981
11982 void
11983 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11984 {
11985         g_assert_not_reached ();
11986 }
11987
11988 void
11989 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11990 {
11991         g_assert_not_reached ();
11992 }
11993
11994 void
11995 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11996 {
11997         g_assert_not_reached ();
11998 }
11999
12000 void
12001 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12002 {
12003         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12004 }
12005
12006 void
12007 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12008 {
12009         g_assert_not_reached ();
12010 }
12011
12012 void
12013 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12014 {
12015         g_assert_not_reached ();
12016 }
12017
12018 MonoReflectionModule *
12019 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12020 {
12021         g_assert_not_reached ();
12022         return NULL;
12023 }
12024
12025 guint32
12026 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12027 {
12028         g_assert_not_reached ();
12029         return 0;
12030 }
12031
12032 guint32
12033 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12034 {
12035         g_assert_not_reached ();
12036         return 0;
12037 }
12038
12039 guint32
12040 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12041                                                  gboolean create_open_instance, gboolean register_token)
12042 {
12043         g_assert_not_reached ();
12044         return 0;
12045 }
12046
12047 void
12048 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12049 {
12050 }
12051
12052 void
12053 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12054 {
12055         g_assert_not_reached ();
12056 }
12057
12058 void
12059 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12060 {
12061         *overrides = NULL;
12062         *num_overrides = 0;
12063 }
12064
12065 MonoReflectionEvent *
12066 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12067 {
12068         g_assert_not_reached ();
12069         return NULL;
12070 }
12071
12072 MonoReflectionType*
12073 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12074 {
12075         g_assert_not_reached ();
12076         return NULL;
12077 }
12078
12079 void
12080 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12081 {
12082         g_assert_not_reached ();
12083 }
12084
12085 MonoArray *
12086 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12087 {
12088         g_assert_not_reached ();
12089         return NULL;
12090 }
12091
12092 MonoArray *
12093 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12094 {
12095         g_assert_not_reached ();
12096         return NULL;
12097 }
12098
12099 void 
12100 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12101 {
12102 }
12103
12104 gpointer
12105 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12106 {
12107         return NULL;
12108 }
12109
12110 MonoType*
12111 mono_reflection_type_get_handle (MonoReflectionType* ref)
12112 {
12113         if (!ref)
12114                 return NULL;
12115         return ref->type;
12116 }
12117
12118 void
12119 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12120 {
12121         g_assert_not_reached ();
12122 }
12123
12124 #endif /* DISABLE_REFLECTION_EMIT */
12125
12126 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12127 const static guint32 declsec_flags_map[] = {
12128         0x00000000,                                     /* empty */
12129         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12130         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12131         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12132         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12133         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12134         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12135         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12136         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12137         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12138         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12139         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12140         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12141         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12142         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12143         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12144         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12145         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12146         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12147 };
12148
12149 /*
12150  * Returns flags that includes all available security action associated to the handle.
12151  * @token: metadata token (either for a class or a method)
12152  * @image: image where resides the metadata.
12153  */
12154 static guint32
12155 mono_declsec_get_flags (MonoImage *image, guint32 token)
12156 {
12157         int index = mono_metadata_declsec_from_index (image, token);
12158         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12159         guint32 result = 0;
12160         guint32 action;
12161         int i;
12162
12163         /* HasSecurity can be present for other, not specially encoded, attributes,
12164            e.g. SuppressUnmanagedCodeSecurityAttribute */
12165         if (index < 0)
12166                 return 0;
12167
12168         for (i = index; i < t->rows; i++) {
12169                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12170
12171                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12172                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12173                         break;
12174
12175                 action = cols [MONO_DECL_SECURITY_ACTION];
12176                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12177                         result |= declsec_flags_map [action];
12178                 } else {
12179                         g_assert_not_reached ();
12180                 }
12181         }
12182         return result;
12183 }
12184
12185 /*
12186  * Get the security actions (in the form of flags) associated with the specified method.
12187  *
12188  * @method: The method for which we want the declarative security flags.
12189  * Return the declarative security flags for the method (only).
12190  *
12191  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12192  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12193  */
12194 guint32
12195 mono_declsec_flags_from_method (MonoMethod *method)
12196 {
12197         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12198                 /* FIXME: No cache (for the moment) */
12199                 guint32 idx = mono_method_get_index (method);
12200                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12201                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12202                 return mono_declsec_get_flags (method->klass->image, idx);
12203         }
12204         return 0;
12205 }
12206
12207 /*
12208  * Get the security actions (in the form of flags) associated with the specified class.
12209  *
12210  * @klass: The class for which we want the declarative security flags.
12211  * Return the declarative security flags for the class.
12212  *
12213  * Note: We cache the flags inside the MonoClass structure as this will get 
12214  *       called very often (at least for each method).
12215  */
12216 guint32
12217 mono_declsec_flags_from_class (MonoClass *klass)
12218 {
12219         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12220                 if (!klass->ext || !klass->ext->declsec_flags) {
12221                         guint32 idx;
12222
12223                         idx = mono_metadata_token_index (klass->type_token);
12224                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12225                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12226                         mono_loader_lock ();
12227                         mono_class_alloc_ext (klass);
12228                         mono_loader_unlock ();
12229                         /* we cache the flags on classes */
12230                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12231                 }
12232                 return klass->ext->declsec_flags;
12233         }
12234         return 0;
12235 }
12236
12237 /*
12238  * Get the security actions (in the form of flags) associated with the specified assembly.
12239  *
12240  * @assembly: The assembly for which we want the declarative security flags.
12241  * Return the declarative security flags for the assembly.
12242  */
12243 guint32
12244 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12245 {
12246         guint32 idx = 1; /* there is only one assembly */
12247         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12248         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12249         return mono_declsec_get_flags (assembly->image, idx);
12250 }
12251
12252
12253 /*
12254  * Fill actions for the specific index (which may either be an encoded class token or
12255  * an encoded method token) from the metadata image.
12256  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12257  */
12258 static MonoBoolean
12259 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12260         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12261 {
12262         MonoBoolean result = FALSE;
12263         MonoTableInfo *t;
12264         guint32 cols [MONO_DECL_SECURITY_SIZE];
12265         int index = mono_metadata_declsec_from_index (image, token);
12266         int i;
12267
12268         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12269         for (i = index; i < t->rows; i++) {
12270                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12271
12272                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12273                         return result;
12274
12275                 /* if present only replace (class) permissions with method permissions */
12276                 /* if empty accept either class or method permissions */
12277                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12278                         if (!actions->demand.blob) {
12279                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12280                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12281                                 actions->demand.blob = (char*) (blob + 2);
12282                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12283                                 result = TRUE;
12284                         }
12285                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12286                         if (!actions->noncasdemand.blob) {
12287                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12288                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12289                                 actions->noncasdemand.blob = (char*) (blob + 2);
12290                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12291                                 result = TRUE;
12292                         }
12293                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12294                         if (!actions->demandchoice.blob) {
12295                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12296                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12297                                 actions->demandchoice.blob = (char*) (blob + 2);
12298                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12299                                 result = TRUE;
12300                         }
12301                 }
12302         }
12303
12304         return result;
12305 }
12306
12307 static MonoBoolean
12308 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12309         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12310 {
12311         guint32 idx = mono_metadata_token_index (klass->type_token);
12312         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12313         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12314         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12315 }
12316
12317 static MonoBoolean
12318 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12319         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12320 {
12321         guint32 idx = mono_method_get_index (method);
12322         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12323         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12324         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12325 }
12326
12327 /*
12328  * Collect all actions (that requires to generate code in mini) assigned for
12329  * the specified method.
12330  * Note: Don't use the content of actions if the function return FALSE.
12331  */
12332 MonoBoolean
12333 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12334 {
12335         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12336                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12337         MonoBoolean result = FALSE;
12338         guint32 flags;
12339
12340         /* quick exit if no declarative security is present in the metadata */
12341         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12342                 return FALSE;
12343
12344         /* we want the original as the wrapper is "free" of the security informations */
12345         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12346                 method = mono_marshal_method_from_wrapper (method);
12347                 if (!method)
12348                         return FALSE;
12349         }
12350
12351         /* First we look for method-level attributes */
12352         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12353                 mono_class_init (method->klass);
12354                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12355
12356                 result = mono_declsec_get_method_demands_params (method, demands, 
12357                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12358         }
12359
12360         /* Here we use (or create) the class declarative cache to look for demands */
12361         flags = mono_declsec_flags_from_class (method->klass);
12362         if (flags & mask) {
12363                 if (!result) {
12364                         mono_class_init (method->klass);
12365                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12366                 }
12367                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12368                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12369         }
12370
12371         /* The boolean return value is used as a shortcut in case nothing needs to
12372            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12373         return result;
12374 }
12375
12376
12377 /*
12378  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12379  *
12380  * Note: Don't use the content of actions if the function return FALSE.
12381  */
12382 MonoBoolean
12383 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12384 {
12385         MonoBoolean result = FALSE;
12386         guint32 flags;
12387
12388         /* quick exit if no declarative security is present in the metadata */
12389         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12390                 return FALSE;
12391
12392         /* we want the original as the wrapper is "free" of the security informations */
12393         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12394                 method = mono_marshal_method_from_wrapper (method);
12395                 if (!method)
12396                         return FALSE;
12397         }
12398
12399         /* results are independant - zeroize both */
12400         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12401         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12402
12403         /* First we look for method-level attributes */
12404         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12405                 mono_class_init (method->klass);
12406
12407                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12408                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12409         }
12410
12411         /* Here we use (or create) the class declarative cache to look for demands */
12412         flags = mono_declsec_flags_from_class (method->klass);
12413         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12414                 mono_class_init (method->klass);
12415
12416                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12417                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12418         }
12419
12420         return result;
12421 }
12422
12423 /*
12424  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12425  *
12426  * @klass       The inherited class - this is the class that provides the security check (attributes)
12427  * @demans      
12428  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12429  * 
12430  * Note: Don't use the content of actions if the function return FALSE.
12431  */
12432 MonoBoolean
12433 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12434 {
12435         MonoBoolean result = FALSE;
12436         guint32 flags;
12437
12438         /* quick exit if no declarative security is present in the metadata */
12439         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12440                 return FALSE;
12441
12442         /* Here we use (or create) the class declarative cache to look for demands */
12443         flags = mono_declsec_flags_from_class (klass);
12444         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12445                 mono_class_init (klass);
12446                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12447
12448                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12449                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12450         }
12451
12452         return result;
12453 }
12454
12455 /*
12456  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12457  *
12458  * Note: Don't use the content of actions if the function return FALSE.
12459  */
12460 MonoBoolean
12461 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12462 {
12463         /* quick exit if no declarative security is present in the metadata */
12464         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12465                 return FALSE;
12466
12467         /* we want the original as the wrapper is "free" of the security informations */
12468         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12469                 method = mono_marshal_method_from_wrapper (method);
12470                 if (!method)
12471                         return FALSE;
12472         }
12473
12474         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12475                 mono_class_init (method->klass);
12476                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12477
12478                 return mono_declsec_get_method_demands_params (method, demands, 
12479                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12480         }
12481         return FALSE;
12482 }
12483
12484
12485 static MonoBoolean
12486 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12487 {
12488         guint32 cols [MONO_DECL_SECURITY_SIZE];
12489         MonoTableInfo *t;
12490         int i;
12491
12492         int index = mono_metadata_declsec_from_index (image, token);
12493         if (index == -1)
12494                 return FALSE;
12495
12496         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12497         for (i = index; i < t->rows; i++) {
12498                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12499
12500                 /* shortcut - index are ordered */
12501                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12502                         return FALSE;
12503
12504                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12505                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12506                         entry->blob = (char*) (metadata + 2);
12507                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12508                         return TRUE;
12509                 }
12510         }
12511
12512         return FALSE;
12513 }
12514
12515 MonoBoolean
12516 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12517 {
12518         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12519                 guint32 idx = mono_method_get_index (method);
12520                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12521                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12522                 return get_declsec_action (method->klass->image, idx, action, entry);
12523         }
12524         return FALSE;
12525 }
12526
12527 MonoBoolean
12528 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12529 {
12530         /* use cache */
12531         guint32 flags = mono_declsec_flags_from_class (klass);
12532         if (declsec_flags_map [action] & flags) {
12533                 guint32 idx = mono_metadata_token_index (klass->type_token);
12534                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12535                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12536                 return get_declsec_action (klass->image, idx, action, entry);
12537         }
12538         return FALSE;
12539 }
12540
12541 MonoBoolean
12542 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12543 {
12544         guint32 idx = 1; /* there is only one assembly */
12545         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12546         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12547
12548         return get_declsec_action (assembly->image, idx, action, entry);
12549 }
12550
12551 gboolean
12552 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12553 {
12554         MonoObject *res, *exc;
12555         void *params [1];
12556         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12557         static MonoMethod *method = NULL;
12558
12559         if (!System_Reflection_Emit_TypeBuilder) {
12560                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12561                 g_assert (System_Reflection_Emit_TypeBuilder);
12562         }
12563         if (method == NULL) {
12564                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12565                 g_assert (method);
12566         }
12567
12568         /* 
12569          * The result of mono_type_get_object () might be a System.MonoType but we
12570          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12571          */
12572         g_assert (mono_class_get_ref_info (klass));
12573         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12574
12575         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12576
12577         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12578         if (exc)
12579                 return FALSE;
12580         else
12581                 return *(MonoBoolean*)mono_object_unbox (res);
12582 }
12583
12584 /**
12585  * mono_reflection_type_get_type:
12586  * @reftype: the System.Type object
12587  *
12588  * Returns the MonoType* associated with the C# System.Type object @reftype.
12589  */
12590 MonoType*
12591 mono_reflection_type_get_type (MonoReflectionType *reftype)
12592 {
12593         g_assert (reftype);
12594
12595         return mono_reflection_type_get_handle (reftype);
12596 }
12597