Add a third AOT location, alongside ~/.mono/aot-cache and the assembly dir
[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-internals.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 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
206 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
207
208 #if SIZEOF_VOID_P == 4
209 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
210 #else
211 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
212 #endif
213
214 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
215 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
216
217
218 void
219 mono_reflection_init (void)
220 {
221 }
222
223 static void
224 sigbuffer_init (SigBuffer *buf, int size)
225 {
226         buf->buf = g_malloc (size);
227         buf->p = buf->buf;
228         buf->end = buf->buf + size;
229 }
230
231 static void
232 sigbuffer_make_room (SigBuffer *buf, int size)
233 {
234         if (buf->end - buf->p < size) {
235                 int new_size = buf->end - buf->buf + size + 32;
236                 char *p = g_realloc (buf->buf, new_size);
237                 size = buf->p - buf->buf;
238                 buf->buf = p;
239                 buf->p = p + size;
240                 buf->end = buf->buf + new_size;
241         }
242 }
243
244 static void
245 sigbuffer_add_value (SigBuffer *buf, guint32 val)
246 {
247         sigbuffer_make_room (buf, 6);
248         mono_metadata_encode_value (val, buf->p, &buf->p);
249 }
250
251 static void
252 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
253 {
254         sigbuffer_make_room (buf, 1);
255         buf->p [0] = val;
256         buf->p++;
257 }
258
259 static void
260 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
261 {
262         sigbuffer_make_room (buf, size);
263         memcpy (buf->p, p, size);
264         buf->p += size;
265 }
266
267 static void
268 sigbuffer_free (SigBuffer *buf)
269 {
270         g_free (buf->buf);
271 }
272
273 #ifndef DISABLE_REFLECTION_EMIT
274 /**
275  * mp_g_alloc:
276  *
277  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
278  * from the C heap.
279  */
280 static gpointer
281 image_g_malloc (MonoImage *image, guint size)
282 {
283         if (image)
284                 return mono_image_alloc (image, size);
285         else
286                 return g_malloc (size);
287 }
288 #endif /* !DISABLE_REFLECTION_EMIT */
289
290 /**
291  * image_g_alloc0:
292  *
293  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
294  * from the C heap.
295  */
296 static gpointer
297 image_g_malloc0 (MonoImage *image, guint size)
298 {
299         if (image)
300                 return mono_image_alloc0 (image, size);
301         else
302                 return g_malloc0 (size);
303 }
304
305 #ifndef DISABLE_REFLECTION_EMIT
306 static char*
307 image_strdup (MonoImage *image, const char *s)
308 {
309         if (image)
310                 return mono_image_strdup (image, s);
311         else
312                 return g_strdup (s);
313 }
314 #endif
315
316 #define image_g_new(image,struct_type, n_structs)               \
317     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318
319 #define image_g_new0(image,struct_type, n_structs)              \
320     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
321
322
323 static void
324 alloc_table (MonoDynamicTable *table, guint nrows)
325 {
326         table->rows = nrows;
327         g_assert (table->columns);
328         if (nrows + 1 >= table->alloc_rows) {
329                 while (nrows + 1 >= table->alloc_rows) {
330                         if (table->alloc_rows == 0)
331                                 table->alloc_rows = 16;
332                         else
333                                 table->alloc_rows *= 2;
334                 }
335
336                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337         }
338 }
339
340 static void
341 make_room_in_stream (MonoDynamicStream *stream, int size)
342 {
343         if (size <= stream->alloc_size)
344                 return;
345         
346         while (stream->alloc_size <= size) {
347                 if (stream->alloc_size < 4096)
348                         stream->alloc_size = 4096;
349                 else
350                         stream->alloc_size *= 2;
351         }
352         
353         stream->data = g_realloc (stream->data, stream->alloc_size);
354 }
355
356 static guint32
357 string_heap_insert (MonoDynamicStream *sh, const char *str)
358 {
359         guint32 idx;
360         guint32 len;
361         gpointer oldkey, oldval;
362
363         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
364                 return GPOINTER_TO_UINT (oldval);
365
366         len = strlen (str) + 1;
367         idx = sh->index;
368         
369         make_room_in_stream (sh, idx + len);
370
371         /*
372          * We strdup the string even if we already copy them in sh->data
373          * so that the string pointers in the hash remain valid even if
374          * we need to realloc sh->data. We may want to avoid that later.
375          */
376         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
377         memcpy (sh->data + idx, str, len);
378         sh->index += len;
379         return idx;
380 }
381
382 static guint32
383 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
384 {
385         char *name = mono_string_to_utf8 (str);
386         guint32 idx;
387         idx = string_heap_insert (sh, name);
388         g_free (name);
389         return idx;
390 }
391
392 #ifndef DISABLE_REFLECTION_EMIT
393 static void
394 string_heap_init (MonoDynamicStream *sh)
395 {
396         sh->index = 0;
397         sh->alloc_size = 4096;
398         sh->data = g_malloc (4096);
399         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
400         string_heap_insert (sh, "");
401 }
402 #endif
403
404 static guint32
405 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
406 {
407         guint32 idx;
408         
409         make_room_in_stream (stream, stream->index + len);
410         memcpy (stream->data + stream->index, data, len);
411         idx = stream->index;
412         stream->index += len;
413         /* 
414          * align index? Not without adding an additional param that controls it since
415          * we may store a blob value in pieces.
416          */
417         return idx;
418 }
419
420 static guint32
421 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
422 {
423         guint32 idx;
424         
425         make_room_in_stream (stream, stream->index + len);
426         memset (stream->data + stream->index, 0, len);
427         idx = stream->index;
428         stream->index += len;
429         return idx;
430 }
431
432 static void
433 stream_data_align (MonoDynamicStream *stream)
434 {
435         char buf [4] = {0};
436         guint32 count = stream->index % 4;
437
438         /* we assume the stream data will be aligned */
439         if (count)
440                 mono_image_add_stream_data (stream, buf, 4 - count);
441 }
442
443 #ifndef DISABLE_REFLECTION_EMIT
444 static int
445 mono_blob_entry_hash (const char* str)
446 {
447         guint len, h;
448         const char *end;
449         len = mono_metadata_decode_blob_size (str, &str);
450         if (len > 0) {
451                 end = str + len;
452                 h = *str;
453                 for (str += 1; str < end; str++)
454                         h = (h << 5) - h + *str;
455                 return h;
456         } else {
457                 return 0;
458         }
459 }
460
461 static gboolean
462 mono_blob_entry_equal (const char *str1, const char *str2) {
463         int len, len2;
464         const char *end1;
465         const char *end2;
466         len = mono_metadata_decode_blob_size (str1, &end1);
467         len2 = mono_metadata_decode_blob_size (str2, &end2);
468         if (len != len2)
469                 return 0;
470         return memcmp (end1, end2, len) == 0;
471 }
472 #endif
473 static guint32
474 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
475 {
476         guint32 idx;
477         char *copy;
478         gpointer oldkey, oldval;
479
480         copy = g_malloc (s1+s2);
481         memcpy (copy, b1, s1);
482         memcpy (copy + s1, b2, s2);
483         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
484                 g_free (copy);
485                 idx = GPOINTER_TO_UINT (oldval);
486         } else {
487                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
488                 mono_image_add_stream_data (&assembly->blob, b2, s2);
489                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
490         }
491         return idx;
492 }
493
494 static guint32
495 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
496 {
497         char blob_size [8];
498         char *b = blob_size;
499         guint32 size = buf->p - buf->buf;
500         /* store length */
501         g_assert (size <= (buf->end - buf->buf));
502         mono_metadata_encode_value (size, b, &b);
503         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 }
505
506 /*
507  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
508  * dest may be misaligned.
509  */
510 static void
511 swap_with_size (char *dest, const char* val, int len, int nelem) {
512 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
513         int elem;
514
515         for (elem = 0; elem < nelem; ++elem) {
516                 switch (len) {
517                 case 1:
518                         *dest = *val;
519                         break;
520                 case 2:
521                         dest [0] = val [1];
522                         dest [1] = val [0];
523                         break;
524                 case 4:
525                         dest [0] = val [3];
526                         dest [1] = val [2];
527                         dest [2] = val [1];
528                         dest [3] = val [0];
529                         break;
530                 case 8:
531                         dest [0] = val [7];
532                         dest [1] = val [6];
533                         dest [2] = val [5];
534                         dest [3] = val [4];
535                         dest [4] = val [3];
536                         dest [5] = val [2];
537                         dest [6] = val [1];
538                         dest [7] = val [0];
539                         break;
540                 default:
541                         g_assert_not_reached ();
542                 }
543                 dest += len;
544                 val += len;
545         }
546 #else
547         memcpy (dest, val, len * nelem);
548 #endif
549 }
550
551 static guint32
552 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
553 {
554         char blob_size [64];
555         char *b = blob_size;
556         guint32 idx = 0, len;
557
558         len = str->length * 2;
559         mono_metadata_encode_value (len, b, &b);
560 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
561         {
562                 char *swapped = g_malloc (2 * mono_string_length (str));
563                 const char *p = (const char*)mono_string_chars (str);
564
565                 swap_with_size (swapped, p, 2, mono_string_length (str));
566                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
567                 g_free (swapped);
568         }
569 #else
570         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
571 #endif
572         return idx;
573 }
574
575 #ifndef DISABLE_REFLECTION_EMIT
576 static MonoClass *
577 default_class_from_mono_type (MonoType *type)
578 {
579         switch (type->type) {
580         case MONO_TYPE_OBJECT:
581                 return mono_defaults.object_class;
582         case MONO_TYPE_VOID:
583                 return mono_defaults.void_class;
584         case MONO_TYPE_BOOLEAN:
585                 return mono_defaults.boolean_class;
586         case MONO_TYPE_CHAR:
587                 return mono_defaults.char_class;
588         case MONO_TYPE_I1:
589                 return mono_defaults.sbyte_class;
590         case MONO_TYPE_U1:
591                 return mono_defaults.byte_class;
592         case MONO_TYPE_I2:
593                 return mono_defaults.int16_class;
594         case MONO_TYPE_U2:
595                 return mono_defaults.uint16_class;
596         case MONO_TYPE_I4:
597                 return mono_defaults.int32_class;
598         case MONO_TYPE_U4:
599                 return mono_defaults.uint32_class;
600         case MONO_TYPE_I:
601                 return mono_defaults.int_class;
602         case MONO_TYPE_U:
603                 return mono_defaults.uint_class;
604         case MONO_TYPE_I8:
605                 return mono_defaults.int64_class;
606         case MONO_TYPE_U8:
607                 return mono_defaults.uint64_class;
608         case MONO_TYPE_R4:
609                 return mono_defaults.single_class;
610         case MONO_TYPE_R8:
611                 return mono_defaults.double_class;
612         case MONO_TYPE_STRING:
613                 return mono_defaults.string_class;
614         default:
615                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
616                 g_assert_not_reached ();
617         }
618         
619         return NULL;
620 }
621 #endif
622
623 /*
624  * mono_class_get_ref_info:
625  *
626  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
627  */
628 gpointer
629 mono_class_get_ref_info (MonoClass *klass)
630 {
631         if (klass->ref_info_handle == 0)
632                 return NULL;
633         else
634                 return mono_gchandle_get_target (klass->ref_info_handle);
635 }
636
637 void
638 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
639 {
640         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
641         g_assert (klass->ref_info_handle != 0);
642 }
643
644 void
645 mono_class_free_ref_info (MonoClass *klass)
646 {
647         if (klass->ref_info_handle) {
648                 mono_gchandle_free (klass->ref_info_handle);
649                 klass->ref_info_handle = 0;
650         }
651 }
652
653 static void
654 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
655 {
656         int i;
657         MonoGenericInst *class_inst;
658         MonoClass *klass;
659
660         g_assert (gclass);
661
662         class_inst = gclass->context.class_inst;
663
664         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
665         klass = gclass->container_class;
666         sigbuffer_add_value (buf, klass->byval_arg.type);
667         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
668
669         sigbuffer_add_value (buf, class_inst->type_argc);
670         for (i = 0; i < class_inst->type_argc; ++i)
671                 encode_type (assembly, class_inst->type_argv [i], buf);
672
673 }
674
675 static void
676 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
677 {
678         if (!type) {
679                 g_assert_not_reached ();
680                 return;
681         }
682                 
683         if (type->byref)
684                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
685
686         switch (type->type){
687         case MONO_TYPE_VOID:
688         case MONO_TYPE_BOOLEAN:
689         case MONO_TYPE_CHAR:
690         case MONO_TYPE_I1:
691         case MONO_TYPE_U1:
692         case MONO_TYPE_I2:
693         case MONO_TYPE_U2:
694         case MONO_TYPE_I4:
695         case MONO_TYPE_U4:
696         case MONO_TYPE_I8:
697         case MONO_TYPE_U8:
698         case MONO_TYPE_R4:
699         case MONO_TYPE_R8:
700         case MONO_TYPE_I:
701         case MONO_TYPE_U:
702         case MONO_TYPE_STRING:
703         case MONO_TYPE_OBJECT:
704         case MONO_TYPE_TYPEDBYREF:
705                 sigbuffer_add_value (buf, type->type);
706                 break;
707         case MONO_TYPE_PTR:
708                 sigbuffer_add_value (buf, type->type);
709                 encode_type (assembly, type->data.type, buf);
710                 break;
711         case MONO_TYPE_SZARRAY:
712                 sigbuffer_add_value (buf, type->type);
713                 encode_type (assembly, &type->data.klass->byval_arg, buf);
714                 break;
715         case MONO_TYPE_VALUETYPE:
716         case MONO_TYPE_CLASS: {
717                 MonoClass *k = mono_class_from_mono_type (type);
718
719                 if (k->generic_container) {
720                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
721                         encode_generic_class (assembly, gclass, buf);
722                 } else {
723                         /*
724                          * Make sure we use the correct type.
725                          */
726                         sigbuffer_add_value (buf, k->byval_arg.type);
727                         /*
728                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
729                          * otherwise two typerefs could point to the same type, leading to
730                          * verification errors.
731                          */
732                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
733                 }
734                 break;
735         }
736         case MONO_TYPE_ARRAY:
737                 sigbuffer_add_value (buf, type->type);
738                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
739                 sigbuffer_add_value (buf, type->data.array->rank);
740                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
741                 sigbuffer_add_value (buf, 0);
742                 break;
743         case MONO_TYPE_GENERICINST:
744                 encode_generic_class (assembly, type->data.generic_class, buf);
745                 break;
746         case MONO_TYPE_VAR:
747         case MONO_TYPE_MVAR:
748                 sigbuffer_add_value (buf, type->type);
749                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
750                 break;
751         default:
752                 g_error ("need to encode type %x", type->type);
753         }
754 }
755
756 static void
757 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
758 {
759         if (!type) {
760                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
761                 return;
762         }
763
764         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
765 }
766
767 static void
768 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
769 {
770         int i;
771
772         if (modreq) {
773                 for (i = 0; i < mono_array_length (modreq); ++i) {
774                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
775                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
776                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
777                 }
778         }
779         if (modopt) {
780                 for (i = 0; i < mono_array_length (modopt); ++i) {
781                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
782                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
783                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
784                 }
785         }
786 }
787
788 #ifndef DISABLE_REFLECTION_EMIT
789 static guint32
790 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
791 {
792         SigBuffer buf;
793         int i;
794         guint32 nparams =  sig->param_count;
795         guint32 idx;
796
797         if (!assembly->save)
798                 return 0;
799
800         sigbuffer_init (&buf, 32);
801         /*
802          * FIXME: vararg, explicit_this, differenc call_conv values...
803          */
804         idx = sig->call_convention;
805         if (sig->hasthis)
806                 idx |= 0x20; /* hasthis */
807         if (sig->generic_param_count)
808                 idx |= 0x10; /* generic */
809         sigbuffer_add_byte (&buf, idx);
810         if (sig->generic_param_count)
811                 sigbuffer_add_value (&buf, sig->generic_param_count);
812         sigbuffer_add_value (&buf, nparams);
813         encode_type (assembly, sig->ret, &buf);
814         for (i = 0; i < nparams; ++i) {
815                 if (i == sig->sentinelpos)
816                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
817                 encode_type (assembly, sig->params [i], &buf);
818         }
819         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
820         sigbuffer_free (&buf);
821         return idx;
822 }
823 #endif
824
825 static guint32
826 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
827 {
828         /*
829          * FIXME: reuse code from method_encode_signature().
830          */
831         SigBuffer buf;
832         int i;
833         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
834         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
835         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
836         guint32 idx;
837
838         sigbuffer_init (&buf, 32);
839         /* LAMESPEC: all the call conv spec is foobared */
840         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
841         if (mb->call_conv & 2)
842                 idx |= 0x5; /* vararg */
843         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
844                 idx |= 0x20; /* hasthis */
845         if (ngparams)
846                 idx |= 0x10; /* generic */
847         sigbuffer_add_byte (&buf, idx);
848         if (ngparams)
849                 sigbuffer_add_value (&buf, ngparams);
850         sigbuffer_add_value (&buf, nparams + notypes);
851         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
852         encode_reflection_type (assembly, mb->rtype, &buf);
853         for (i = 0; i < nparams; ++i) {
854                 MonoArray *modreq = NULL;
855                 MonoArray *modopt = NULL;
856                 MonoReflectionType *pt;
857
858                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
859                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
860                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
861                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
862                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
863                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
864                 encode_reflection_type (assembly, pt, &buf);
865         }
866         if (notypes)
867                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
868         for (i = 0; i < notypes; ++i) {
869                 MonoReflectionType *pt;
870
871                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
872                 encode_reflection_type (assembly, pt, &buf);
873         }
874
875         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
876         sigbuffer_free (&buf);
877         return idx;
878 }
879
880 static guint32
881 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
882 {
883         MonoDynamicTable *table;
884         guint32 *values;
885         guint32 idx, sig_idx;
886         guint nl = mono_array_length (ilgen->locals);
887         SigBuffer buf;
888         int i;
889
890         sigbuffer_init (&buf, 32);
891         sigbuffer_add_value (&buf, 0x07);
892         sigbuffer_add_value (&buf, nl);
893         for (i = 0; i < nl; ++i) {
894                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
895                 
896                 if (lb->is_pinned)
897                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
898                 
899                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
900         }
901         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
902         sigbuffer_free (&buf);
903
904         if (assembly->standalonesig_cache == NULL)
905                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
906         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
907         if (idx)
908                 return idx;
909
910         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
911         idx = table->next_idx ++;
912         table->rows ++;
913         alloc_table (table, table->rows);
914         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
915
916         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
917
918         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
919
920         return idx;
921 }
922
923 static guint32
924 method_count_clauses (MonoReflectionILGen *ilgen)
925 {
926         guint32 num_clauses = 0;
927         int i;
928
929         MonoILExceptionInfo *ex_info;
930         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
931                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
932                 if (ex_info->handlers)
933                         num_clauses += mono_array_length (ex_info->handlers);
934                 else
935                         num_clauses++;
936         }
937
938         return num_clauses;
939 }
940
941 #ifndef DISABLE_REFLECTION_EMIT
942 static MonoExceptionClause*
943 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
944 {
945         MonoExceptionClause *clauses;
946         MonoExceptionClause *clause;
947         MonoILExceptionInfo *ex_info;
948         MonoILExceptionBlock *ex_block;
949         guint32 finally_start;
950         int i, j, clause_index;;
951
952         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
953
954         clause_index = 0;
955         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
956                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
957                 finally_start = ex_info->start + ex_info->len;
958                 if (!ex_info->handlers)
959                         continue;
960                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
961                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
962                         clause = &(clauses [clause_index]);
963
964                         clause->flags = ex_block->type;
965                         clause->try_offset = ex_info->start;
966
967                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
968                                 clause->try_len = finally_start - ex_info->start;
969                         else
970                                 clause->try_len = ex_info->len;
971                         clause->handler_offset = ex_block->start;
972                         clause->handler_len = ex_block->len;
973                         if (ex_block->extype) {
974                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
975                         } else {
976                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
977                                         clause->data.filter_offset = ex_block->filter_offset;
978                                 else
979                                         clause->data.filter_offset = 0;
980                         }
981                         finally_start = ex_block->start + ex_block->len;
982
983                         clause_index ++;
984                 }
985         }
986
987         return clauses;
988 }
989 #endif /* !DISABLE_REFLECTION_EMIT */
990
991 static guint32
992 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
993 {
994         char flags = 0;
995         guint32 idx;
996         guint32 code_size;
997         gint32 max_stack, i;
998         gint32 num_locals = 0;
999         gint32 num_exception = 0;
1000         gint maybe_small;
1001         guint32 fat_flags;
1002         char fat_header [12];
1003         guint32 int_value;
1004         guint16 short_value;
1005         guint32 local_sig = 0;
1006         guint32 header_size = 12;
1007         MonoArray *code;
1008
1009         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1010                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1011                 return 0;
1012
1013         /*if (mb->name)
1014                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1015         if (mb->ilgen) {
1016                 code = mb->ilgen->code;
1017                 code_size = mb->ilgen->code_len;
1018                 max_stack = mb->ilgen->max_stack;
1019                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1020                 if (mb->ilgen->ex_handlers)
1021                         num_exception = method_count_clauses (mb->ilgen);
1022         } else {
1023                 code = mb->code;
1024                 if (code == NULL){
1025                         char *name = mono_string_to_utf8 (mb->name);
1026                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1027                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1028                         g_free (str);
1029                         g_free (name);
1030                         mono_raise_exception (exception);
1031                 }
1032
1033                 code_size = mono_array_length (code);
1034                 max_stack = 8; /* we probably need to run a verifier on the code... */
1035         }
1036
1037         stream_data_align (&assembly->code);
1038
1039         /* check for exceptions, maxstack, locals */
1040         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1041         if (maybe_small) {
1042                 if (code_size < 64 && !(code_size & 1)) {
1043                         flags = (code_size << 2) | 0x2;
1044                 } else if (code_size < 32 && (code_size & 1)) {
1045                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1046                 } else {
1047                         goto fat_header;
1048                 }
1049                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1050                 /* add to the fixup todo list */
1051                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1052                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1053                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1054                 return assembly->text_rva + idx;
1055         } 
1056 fat_header:
1057         if (num_locals)
1058                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1059         /* 
1060          * FIXME: need to set also the header size in fat_flags.
1061          * (and more sects and init locals flags)
1062          */
1063         fat_flags =  0x03;
1064         if (num_exception)
1065                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1066         if (mb->init_locals)
1067                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1068         fat_header [0] = fat_flags;
1069         fat_header [1] = (header_size / 4 ) << 4;
1070         short_value = GUINT16_TO_LE (max_stack);
1071         memcpy (fat_header + 2, &short_value, 2);
1072         int_value = GUINT32_TO_LE (code_size);
1073         memcpy (fat_header + 4, &int_value, 4);
1074         int_value = GUINT32_TO_LE (local_sig);
1075         memcpy (fat_header + 8, &int_value, 4);
1076         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1077         /* add to the fixup todo list */
1078         if (mb->ilgen && mb->ilgen->num_token_fixups)
1079                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1080         
1081         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1082         if (num_exception) {
1083                 unsigned char sheader [4];
1084                 MonoILExceptionInfo * ex_info;
1085                 MonoILExceptionBlock * ex_block;
1086                 int j;
1087
1088                 stream_data_align (&assembly->code);
1089                 /* always use fat format for now */
1090                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1091                 num_exception *= 6 * sizeof (guint32);
1092                 num_exception += 4; /* include the size of the header */
1093                 sheader [1] = num_exception & 0xff;
1094                 sheader [2] = (num_exception >> 8) & 0xff;
1095                 sheader [3] = (num_exception >> 16) & 0xff;
1096                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1097                 /* fat header, so we are already aligned */
1098                 /* reverse order */
1099                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1100                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1101                         if (ex_info->handlers) {
1102                                 int finally_start = ex_info->start + ex_info->len;
1103                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1104                                         guint32 val;
1105                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1106                                         /* the flags */
1107                                         val = GUINT32_TO_LE (ex_block->type);
1108                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109                                         /* try offset */
1110                                         val = GUINT32_TO_LE (ex_info->start);
1111                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1112                                         /* need fault, too, probably */
1113                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1114                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1115                                         else
1116                                                 val = GUINT32_TO_LE (ex_info->len);
1117                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118                                         /* handler offset */
1119                                         val = GUINT32_TO_LE (ex_block->start);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /* handler len */
1122                                         val = GUINT32_TO_LE (ex_block->len);
1123                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1124                                         finally_start = ex_block->start + ex_block->len;
1125                                         if (ex_block->extype) {
1126                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1127                                         } else {
1128                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129                                                         val = ex_block->filter_offset;
1130                                                 else
1131                                                         val = 0;
1132                                         }
1133                                         val = GUINT32_TO_LE (val);
1134                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1135                                         /*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", 
1136                                                         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);*/
1137                                 }
1138                         } else {
1139                                 g_error ("No clauses for ex info block %d", i);
1140                         }
1141                 }
1142         }
1143         return assembly->text_rva + idx;
1144 }
1145
1146 static guint32
1147 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1148 {
1149         int i;
1150         MonoDynamicTable *table;
1151         guint32 *values;
1152         
1153         table = &assembly->tables [table_idx];
1154
1155         g_assert (col < table->columns);
1156
1157         values = table->values + table->columns;
1158         for (i = 1; i <= table->rows; ++i) {
1159                 if (values [col] == token)
1160                         return i;
1161                 values += table->columns;
1162         }
1163         return 0;
1164 }
1165
1166 /*
1167  * LOCKING: Acquires the loader lock. 
1168  */
1169 static MonoCustomAttrInfo*
1170 lookup_custom_attr (MonoImage *image, gpointer member)
1171 {
1172         MonoCustomAttrInfo* res;
1173
1174         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1175
1176         if (!res)
1177                 return NULL;
1178
1179         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1180         res->cached = 0;
1181         return res;
1182 }
1183
1184 static gboolean
1185 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1186 {
1187         /* FIXME: Need to do more checks */
1188         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1189                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1190
1191                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1192                         return FALSE;
1193         }
1194
1195         return TRUE;
1196 }
1197
1198 static MonoCustomAttrInfo*
1199 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1200 {
1201         int i, index, count, not_visible;
1202         MonoCustomAttrInfo *ainfo;
1203         MonoReflectionCustomAttr *cattr;
1204
1205         if (!cattrs)
1206                 return NULL;
1207         /* FIXME: check in assembly the Run flag is set */
1208
1209         count = mono_array_length (cattrs);
1210
1211         /* Skip nonpublic attributes since MS.NET seems to do the same */
1212         /* FIXME: This needs to be done more globally */
1213         not_visible = 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                         not_visible ++;
1218         }
1219         count -= not_visible;
1220
1221         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1222
1223         ainfo->image = image;
1224         ainfo->num_attrs = count;
1225         ainfo->cached = alloc_img != NULL;
1226         index = 0;
1227         for (i = 0; i < count; ++i) {
1228                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1229                 if (custom_attr_visible (image, cattr)) {
1230                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1231                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1232                         ainfo->attrs [index].ctor = cattr->ctor->method;
1233                         ainfo->attrs [index].data = saved;
1234                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1235                         index ++;
1236                 }
1237         }
1238
1239         return ainfo;
1240 }
1241
1242 #ifndef DISABLE_REFLECTION_EMIT
1243 /*
1244  * LOCKING: Acquires the loader lock. 
1245  */
1246 static void
1247 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1248 {
1249         MonoCustomAttrInfo *ainfo, *tmp;
1250
1251         if (!cattrs || !mono_array_length (cattrs))
1252                 return;
1253
1254         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1255
1256         mono_loader_lock ();
1257         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1258         if (tmp)
1259                 mono_custom_attrs_free (tmp);
1260         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1261         mono_loader_unlock ();
1262
1263 }
1264 #endif
1265
1266 void
1267 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1268 {
1269         if (!ainfo->cached)
1270                 g_free (ainfo);
1271 }
1272
1273 /*
1274  * idx is the table index of the object
1275  * type is one of MONO_CUSTOM_ATTR_*
1276  */
1277 static void
1278 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1279 {
1280         MonoDynamicTable *table;
1281         MonoReflectionCustomAttr *cattr;
1282         guint32 *values;
1283         guint32 count, i, token;
1284         char blob_size [6];
1285         char *p = blob_size;
1286         
1287         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1288         if (!cattrs)
1289                 return;
1290         count = mono_array_length (cattrs);
1291         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1292         table->rows += count;
1293         alloc_table (table, table->rows);
1294         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1295         idx <<= MONO_CUSTOM_ATTR_BITS;
1296         idx |= type;
1297         for (i = 0; i < count; ++i) {
1298                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1299                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1300                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1301                 type = mono_metadata_token_index (token);
1302                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1303                 switch (mono_metadata_token_table (token)) {
1304                 case MONO_TABLE_METHOD:
1305                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1306                         /*
1307                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1308                          * method, not the one returned by mono_image_create_token ().
1309                          */
1310                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1311                         break;
1312                 case MONO_TABLE_MEMBERREF:
1313                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1314                         break;
1315                 default:
1316                         g_warning ("got wrong token in custom attr");
1317                         continue;
1318                 }
1319                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1320                 p = blob_size;
1321                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1322                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1323                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1324                 values += MONO_CUSTOM_ATTR_SIZE;
1325                 ++table->next_idx;
1326         }
1327 }
1328
1329 static void
1330 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1331 {
1332         MonoDynamicTable *table;
1333         guint32 *values;
1334         guint32 count, i, idx;
1335         MonoReflectionPermissionSet *perm;
1336
1337         if (!permissions)
1338                 return;
1339
1340         count = mono_array_length (permissions);
1341         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1342         table->rows += count;
1343         alloc_table (table, table->rows);
1344
1345         for (i = 0; i < mono_array_length (permissions); ++i) {
1346                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1347
1348                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1349
1350                 idx = mono_metadata_token_index (parent_token);
1351                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1352                 switch (mono_metadata_token_table (parent_token)) {
1353                 case MONO_TABLE_TYPEDEF:
1354                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1355                         break;
1356                 case MONO_TABLE_METHOD:
1357                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1358                         break;
1359                 case MONO_TABLE_ASSEMBLY:
1360                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1361                         break;
1362                 default:
1363                         g_assert_not_reached ();
1364                 }
1365
1366                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1367                 values [MONO_DECL_SECURITY_PARENT] = idx;
1368                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1369
1370                 ++table->next_idx;
1371         }
1372 }
1373
1374 /*
1375  * Fill in the MethodDef and ParamDef tables for a method.
1376  * This is used for both normal methods and constructors.
1377  */
1378 static void
1379 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1380 {
1381         MonoDynamicTable *table;
1382         guint32 *values;
1383         guint i, count;
1384
1385         /* room in this table is already allocated */
1386         table = &assembly->tables [MONO_TABLE_METHOD];
1387         *mb->table_idx = table->next_idx ++;
1388         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1389         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1390         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1391         values [MONO_METHOD_FLAGS] = mb->attrs;
1392         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1393         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1394         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1395         
1396         table = &assembly->tables [MONO_TABLE_PARAM];
1397         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1398
1399         mono_image_add_decl_security (assembly, 
1400                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1401
1402         if (mb->pinfo) {
1403                 MonoDynamicTable *mtable;
1404                 guint32 *mvalues;
1405                 
1406                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1407                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1408                 
1409                 count = 0;
1410                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1411                         if (mono_array_get (mb->pinfo, gpointer, i))
1412                                 count++;
1413                 }
1414                 table->rows += count;
1415                 alloc_table (table, table->rows);
1416                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1417                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1418                         MonoReflectionParamBuilder *pb;
1419                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1420                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1421                                 values [MONO_PARAM_SEQUENCE] = i;
1422                                 if (pb->name != NULL) {
1423                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1424                                 } else {
1425                                         values [MONO_PARAM_NAME] = 0;
1426                                 }
1427                                 values += MONO_PARAM_SIZE;
1428                                 if (pb->marshal_info) {
1429                                         mtable->rows++;
1430                                         alloc_table (mtable, mtable->rows);
1431                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1432                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1433                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1434                                 }
1435                                 pb->table_idx = table->next_idx++;
1436                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1437                                         guint32 field_type = 0;
1438                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1439                                         mtable->rows ++;
1440                                         alloc_table (mtable, mtable->rows);
1441                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1442                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1443                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1444                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1445                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1446                                 }
1447                         }
1448                 }
1449         }
1450 }
1451
1452 #ifndef DISABLE_REFLECTION_EMIT
1453 static void
1454 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1455 {
1456         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1457
1458         rmb->ilgen = mb->ilgen;
1459         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1460         rmb->parameters = mb->parameters;
1461         rmb->generic_params = mb->generic_params;
1462         rmb->generic_container = mb->generic_container;
1463         rmb->opt_types = NULL;
1464         rmb->pinfo = mb->pinfo;
1465         rmb->attrs = mb->attrs;
1466         rmb->iattrs = mb->iattrs;
1467         rmb->call_conv = mb->call_conv;
1468         rmb->code = mb->code;
1469         rmb->type = mb->type;
1470         rmb->name = mb->name;
1471         rmb->table_idx = &mb->table_idx;
1472         rmb->init_locals = mb->init_locals;
1473         rmb->skip_visibility = FALSE;
1474         rmb->return_modreq = mb->return_modreq;
1475         rmb->return_modopt = mb->return_modopt;
1476         rmb->param_modreq = mb->param_modreq;
1477         rmb->param_modopt = mb->param_modopt;
1478         rmb->permissions = mb->permissions;
1479         rmb->mhandle = mb->mhandle;
1480         rmb->nrefs = 0;
1481         rmb->refs = NULL;
1482
1483         if (mb->dll) {
1484                 rmb->charset = mb->charset;
1485                 rmb->extra_flags = mb->extra_flags;
1486                 rmb->native_cc = mb->native_cc;
1487                 rmb->dllentry = mb->dllentry;
1488                 rmb->dll = mb->dll;
1489         }
1490 }
1491
1492 static void
1493 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1494 {
1495         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1496
1497         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1498
1499         rmb->ilgen = mb->ilgen;
1500         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1501         rmb->parameters = mb->parameters;
1502         rmb->generic_params = NULL;
1503         rmb->generic_container = NULL;
1504         rmb->opt_types = NULL;
1505         rmb->pinfo = mb->pinfo;
1506         rmb->attrs = mb->attrs;
1507         rmb->iattrs = mb->iattrs;
1508         rmb->call_conv = mb->call_conv;
1509         rmb->code = NULL;
1510         rmb->type = mb->type;
1511         rmb->name = mono_string_new (mono_domain_get (), name);
1512         rmb->table_idx = &mb->table_idx;
1513         rmb->init_locals = mb->init_locals;
1514         rmb->skip_visibility = FALSE;
1515         rmb->return_modreq = NULL;
1516         rmb->return_modopt = NULL;
1517         rmb->param_modreq = mb->param_modreq;
1518         rmb->param_modopt = mb->param_modopt;
1519         rmb->permissions = mb->permissions;
1520         rmb->mhandle = mb->mhandle;
1521         rmb->nrefs = 0;
1522         rmb->refs = NULL;
1523 }
1524
1525 static void
1526 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1527 {
1528         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1529
1530         rmb->ilgen = mb->ilgen;
1531         rmb->rtype = mb->rtype;
1532         rmb->parameters = mb->parameters;
1533         rmb->generic_params = NULL;
1534         rmb->generic_container = NULL;
1535         rmb->opt_types = NULL;
1536         rmb->pinfo = NULL;
1537         rmb->attrs = mb->attrs;
1538         rmb->iattrs = 0;
1539         rmb->call_conv = mb->call_conv;
1540         rmb->code = NULL;
1541         rmb->type = (MonoObject *) mb->owner;
1542         rmb->name = mb->name;
1543         rmb->table_idx = NULL;
1544         rmb->init_locals = mb->init_locals;
1545         rmb->skip_visibility = mb->skip_visibility;
1546         rmb->return_modreq = NULL;
1547         rmb->return_modopt = NULL;
1548         rmb->param_modreq = NULL;
1549         rmb->param_modopt = NULL;
1550         rmb->permissions = NULL;
1551         rmb->mhandle = mb->mhandle;
1552         rmb->nrefs = 0;
1553         rmb->refs = NULL;
1554 }       
1555 #endif
1556
1557 static void
1558 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1559 {
1560         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1561         MonoDynamicTable *table;
1562         guint32 *values;
1563         guint32 tok;
1564         MonoReflectionMethod *m;
1565         int i;
1566
1567         if (!mb->override_methods)
1568                 return;
1569
1570         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1571                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1572
1573                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1574                 table->rows ++;
1575                 alloc_table (table, table->rows);
1576                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1577                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1578                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1579
1580                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1581                 switch (mono_metadata_token_table (tok)) {
1582                 case MONO_TABLE_MEMBERREF:
1583                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1584                         break;
1585                 case MONO_TABLE_METHOD:
1586                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1587                         break;
1588                 default:
1589                         g_assert_not_reached ();
1590                 }
1591                 values [MONO_METHODIMPL_DECLARATION] = tok;
1592         }
1593 }
1594
1595 #ifndef DISABLE_REFLECTION_EMIT
1596 static void
1597 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1598 {
1599         MonoDynamicTable *table;
1600         guint32 *values;
1601         ReflectionMethodBuilder rmb;
1602         int i;
1603
1604         reflection_methodbuilder_from_method_builder (&rmb, mb);
1605
1606         mono_image_basic_method (&rmb, assembly);
1607         mb->table_idx = *rmb.table_idx;
1608
1609         if (mb->dll) { /* It's a P/Invoke method */
1610                 guint32 moduleref;
1611                 /* map CharSet values to on-disk values */
1612                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1613                 int extra_flags = mb->extra_flags;
1614                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1615                 table->rows ++;
1616                 alloc_table (table, table->rows);
1617                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1618                 
1619                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1620                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1621                 if (mb->dllentry)
1622                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1623                 else
1624                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1625                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1626                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1627                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1628                         table->rows ++;
1629                         alloc_table (table, table->rows);
1630                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1631                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1632                 }
1633         }
1634
1635         if (mb->generic_params) {
1636                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1637                 table->rows += mono_array_length (mb->generic_params);
1638                 alloc_table (table, table->rows);
1639                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1640                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1641
1642                         mono_image_get_generic_param_info (
1643                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1644                 }
1645         }
1646
1647 }
1648
1649 static void
1650 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1651 {
1652         ReflectionMethodBuilder rmb;
1653
1654         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1655
1656         mono_image_basic_method (&rmb, assembly);
1657         mb->table_idx = *rmb.table_idx;
1658 }
1659 #endif
1660
1661 static char*
1662 type_get_fully_qualified_name (MonoType *type)
1663 {
1664         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1665 }
1666
1667 static char*
1668 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1669         MonoClass *klass;
1670         MonoAssembly *ta;
1671
1672         klass = mono_class_from_mono_type (type);
1673         if (!klass) 
1674                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1675         ta = klass->image->assembly;
1676         if (assembly_is_dynamic (ta) || (ta == ass)) {
1677                 if (klass->generic_class || klass->generic_container)
1678                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1679                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1680                 else
1681                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1682         }
1683
1684         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1685 }
1686
1687 #ifndef DISABLE_REFLECTION_EMIT
1688 /*field_image is the image to which the eventual custom mods have been encoded against*/
1689 static guint32
1690 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1691 {
1692         SigBuffer buf;
1693         guint32 idx, i, token;
1694
1695         if (!assembly->save)
1696                 return 0;
1697
1698         sigbuffer_init (&buf, 32);
1699         
1700         sigbuffer_add_value (&buf, 0x06);
1701         /* encode custom attributes before the type */
1702         if (type->num_mods) {
1703                 for (i = 0; i < type->num_mods; ++i) {
1704                         if (field_image) {
1705                                 MonoError error;
1706                                 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1707                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1708
1709                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1710                         } else {
1711                                 token = type->modifiers [i].token;
1712                         }
1713
1714                         if (type->modifiers [i].required)
1715                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1716                         else
1717                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1718
1719                         sigbuffer_add_value (&buf, token);
1720                 }
1721         }
1722         encode_type (assembly, type, &buf);
1723         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724         sigbuffer_free (&buf);
1725         return idx;
1726 }
1727 #endif
1728
1729 static guint32
1730 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1731 {
1732         SigBuffer buf;
1733         guint32 idx;
1734         guint32 typespec = 0;
1735         MonoType *type;
1736         MonoClass *class;
1737
1738         init_type_builder_generics (fb->type);
1739
1740         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1741         class = mono_class_from_mono_type (type);
1742
1743         sigbuffer_init (&buf, 32);
1744         
1745         sigbuffer_add_value (&buf, 0x06);
1746         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1747         /* encode custom attributes before the type */
1748
1749         if (class->generic_container)
1750                 typespec = create_typespec (assembly, type);
1751
1752         if (typespec) {
1753                 MonoGenericClass *gclass;
1754                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1755                 encode_generic_class (assembly, gclass, &buf);
1756         } else {
1757                 encode_type (assembly, type, &buf);
1758         }
1759         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1760         sigbuffer_free (&buf);
1761         return idx;
1762 }
1763
1764 static guint32
1765 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1766         char blob_size [64];
1767         char *b = blob_size;
1768         char *p, *box_val;
1769         char* buf;
1770         guint32 idx = 0, len = 0, dummy = 0;
1771
1772         p = buf = g_malloc (64);
1773         if (!val) {
1774                 *ret_type = MONO_TYPE_CLASS;
1775                 len = 4;
1776                 box_val = (char*)&dummy;
1777         } else {
1778                 box_val = ((char*)val) + sizeof (MonoObject);
1779                 *ret_type = val->vtable->klass->byval_arg.type;
1780         }
1781 handle_enum:
1782         switch (*ret_type) {
1783         case MONO_TYPE_BOOLEAN:
1784         case MONO_TYPE_U1:
1785         case MONO_TYPE_I1:
1786                 len = 1;
1787                 break;
1788         case MONO_TYPE_CHAR:
1789         case MONO_TYPE_U2:
1790         case MONO_TYPE_I2:
1791                 len = 2;
1792                 break;
1793         case MONO_TYPE_U4:
1794         case MONO_TYPE_I4:
1795         case MONO_TYPE_R4:
1796                 len = 4;
1797                 break;
1798         case MONO_TYPE_U8:
1799         case MONO_TYPE_I8:
1800                 len = 8;
1801                 break;
1802         case MONO_TYPE_R8:
1803                 len = 8;
1804                 break;
1805         case MONO_TYPE_VALUETYPE: {
1806                 MonoClass *klass = val->vtable->klass;
1807                 
1808                 if (klass->enumtype) {
1809                         *ret_type = mono_class_enum_basetype (klass)->type;
1810                         goto handle_enum;
1811                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1812                         len = 8;
1813                 } else 
1814                         g_error ("we can't encode valuetypes, we should have never reached this line");
1815                 break;
1816         }
1817         case MONO_TYPE_CLASS:
1818                 break;
1819         case MONO_TYPE_STRING: {
1820                 MonoString *str = (MonoString*)val;
1821                 /* there is no signature */
1822                 len = str->length * 2;
1823                 mono_metadata_encode_value (len, b, &b);
1824 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1825                 {
1826                         char *swapped = g_malloc (2 * mono_string_length (str));
1827                         const char *p = (const char*)mono_string_chars (str);
1828
1829                         swap_with_size (swapped, p, 2, mono_string_length (str));
1830                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1831                         g_free (swapped);
1832                 }
1833 #else
1834                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1835 #endif
1836
1837                 g_free (buf);
1838                 return idx;
1839         }
1840         case MONO_TYPE_GENERICINST:
1841                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1842                 goto handle_enum;
1843         default:
1844                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1845         }
1846
1847         /* there is no signature */
1848         mono_metadata_encode_value (len, b, &b);
1849 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1850         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1851         swap_with_size (blob_size, box_val, len, 1);
1852         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1853 #else
1854         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1855 #endif
1856
1857         g_free (buf);
1858         return idx;
1859 }
1860
1861 static guint32
1862 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1863         char *str;
1864         SigBuffer buf;
1865         guint32 idx, len;
1866
1867         sigbuffer_init (&buf, 32);
1868
1869         sigbuffer_add_value (&buf, minfo->type);
1870
1871         switch (minfo->type) {
1872         case MONO_NATIVE_BYVALTSTR:
1873         case MONO_NATIVE_BYVALARRAY:
1874                 sigbuffer_add_value (&buf, minfo->count);
1875                 break;
1876         case MONO_NATIVE_LPARRAY:
1877                 if (minfo->eltype || minfo->has_size) {
1878                         sigbuffer_add_value (&buf, minfo->eltype);
1879                         if (minfo->has_size) {
1880                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1881                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1882
1883                                 /* LAMESPEC: ElemMult is undocumented */
1884                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1885                         }
1886                 }
1887                 break;
1888         case MONO_NATIVE_SAFEARRAY:
1889                 if (minfo->eltype)
1890                         sigbuffer_add_value (&buf, minfo->eltype);
1891                 break;
1892         case MONO_NATIVE_CUSTOM:
1893                 if (minfo->guid) {
1894                         str = mono_string_to_utf8 (minfo->guid);
1895                         len = strlen (str);
1896                         sigbuffer_add_value (&buf, len);
1897                         sigbuffer_add_mem (&buf, str, len);
1898                         g_free (str);
1899                 } else {
1900                         sigbuffer_add_value (&buf, 0);
1901                 }
1902                 /* native type name */
1903                 sigbuffer_add_value (&buf, 0);
1904                 /* custom marshaler type name */
1905                 if (minfo->marshaltype || minfo->marshaltyperef) {
1906                         if (minfo->marshaltyperef)
1907                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1908                         else
1909                                 str = mono_string_to_utf8 (minfo->marshaltype);
1910                         len = strlen (str);
1911                         sigbuffer_add_value (&buf, len);
1912                         sigbuffer_add_mem (&buf, str, len);
1913                         g_free (str);
1914                 } else {
1915                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1916                         sigbuffer_add_value (&buf, 0);
1917                 }
1918                 if (minfo->mcookie) {
1919                         str = mono_string_to_utf8 (minfo->mcookie);
1920                         len = strlen (str);
1921                         sigbuffer_add_value (&buf, len);
1922                         sigbuffer_add_mem (&buf, str, len);
1923                         g_free (str);
1924                 } else {
1925                         sigbuffer_add_value (&buf, 0);
1926                 }
1927                 break;
1928         default:
1929                 break;
1930         }
1931         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1932         sigbuffer_free (&buf);
1933         return idx;
1934 }
1935
1936 static void
1937 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1938 {
1939         MonoDynamicTable *table;
1940         guint32 *values;
1941
1942         /* maybe this fixup should be done in the C# code */
1943         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1944                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1945         table = &assembly->tables [MONO_TABLE_FIELD];
1946         fb->table_idx = table->next_idx ++;
1947         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1948         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1949         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1950         values [MONO_FIELD_FLAGS] = fb->attrs;
1951         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1952
1953         if (fb->offset != -1) {
1954                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1955                 table->rows ++;
1956                 alloc_table (table, table->rows);
1957                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1958                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1959                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1960         }
1961         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1962                 guint32 field_type = 0;
1963                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1964                 table->rows ++;
1965                 alloc_table (table, table->rows);
1966                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1967                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1968                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1969                 values [MONO_CONSTANT_TYPE] = field_type;
1970                 values [MONO_CONSTANT_PADDING] = 0;
1971         }
1972         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1973                 guint32 rva_idx;
1974                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1975                 table->rows ++;
1976                 alloc_table (table, table->rows);
1977                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1978                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1979                 /*
1980                  * We store it in the code section because it's simpler for now.
1981                  */
1982                 if (fb->rva_data) {
1983                         if (mono_array_length (fb->rva_data) >= 10)
1984                                 stream_data_align (&assembly->code);
1985                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1986                 } else
1987                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1988                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1989         }
1990         if (fb->marshal_info) {
1991                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1992                 table->rows ++;
1993                 alloc_table (table, table->rows);
1994                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1995                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1996                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1997         }
1998 }
1999
2000 static guint32
2001 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2002 {
2003         SigBuffer buf;
2004         guint32 nparams = 0;
2005         MonoReflectionMethodBuilder *mb = fb->get_method;
2006         MonoReflectionMethodBuilder *smb = fb->set_method;
2007         guint32 idx, i;
2008
2009         if (mb && mb->parameters)
2010                 nparams = mono_array_length (mb->parameters);
2011         if (!mb && smb && smb->parameters)
2012                 nparams = mono_array_length (smb->parameters) - 1;
2013         sigbuffer_init (&buf, 32);
2014         if (fb->call_conv & 0x20)
2015                 sigbuffer_add_byte (&buf, 0x28);
2016         else
2017                 sigbuffer_add_byte (&buf, 0x08);
2018         sigbuffer_add_value (&buf, nparams);
2019         if (mb) {
2020                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2021                 for (i = 0; i < nparams; ++i) {
2022                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2023                         encode_reflection_type (assembly, pt, &buf);
2024                 }
2025         } else if (smb && smb->parameters) {
2026                 /* the property type is the last param */
2027                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2028                 for (i = 0; i < nparams; ++i) {
2029                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2030                         encode_reflection_type (assembly, pt, &buf);
2031                 }
2032         } else {
2033                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2034         }
2035
2036         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2037         sigbuffer_free (&buf);
2038         return idx;
2039 }
2040
2041 static void
2042 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2043 {
2044         MonoDynamicTable *table;
2045         guint32 *values;
2046         guint num_methods = 0;
2047         guint32 semaidx;
2048
2049         /* 
2050          * we need to set things in the following tables:
2051          * PROPERTYMAP (info already filled in _get_type_info ())
2052          * PROPERTY    (rows already preallocated in _get_type_info ())
2053          * METHOD      (method info already done with the generic method code)
2054          * METHODSEMANTICS
2055          * CONSTANT
2056          */
2057         table = &assembly->tables [MONO_TABLE_PROPERTY];
2058         pb->table_idx = table->next_idx ++;
2059         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2060         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2061         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2062         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2063
2064         /* FIXME: we still don't handle 'other' methods */
2065         if (pb->get_method) num_methods ++;
2066         if (pb->set_method) num_methods ++;
2067
2068         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2069         table->rows += num_methods;
2070         alloc_table (table, table->rows);
2071
2072         if (pb->get_method) {
2073                 semaidx = table->next_idx ++;
2074                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2075                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2076                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2077                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2078         }
2079         if (pb->set_method) {
2080                 semaidx = table->next_idx ++;
2081                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2082                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2083                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2084                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2085         }
2086         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2087                 guint32 field_type = 0;
2088                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2089                 table->rows ++;
2090                 alloc_table (table, table->rows);
2091                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2092                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2093                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2094                 values [MONO_CONSTANT_TYPE] = field_type;
2095                 values [MONO_CONSTANT_PADDING] = 0;
2096         }
2097 }
2098
2099 static void
2100 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2101 {
2102         MonoDynamicTable *table;
2103         guint32 *values;
2104         guint num_methods = 0;
2105         guint32 semaidx;
2106
2107         /* 
2108          * we need to set things in the following tables:
2109          * EVENTMAP (info already filled in _get_type_info ())
2110          * EVENT    (rows already preallocated in _get_type_info ())
2111          * METHOD      (method info already done with the generic method code)
2112          * METHODSEMANTICS
2113          */
2114         table = &assembly->tables [MONO_TABLE_EVENT];
2115         eb->table_idx = table->next_idx ++;
2116         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2117         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2118         values [MONO_EVENT_FLAGS] = eb->attrs;
2119         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2120
2121         /*
2122          * FIXME: we still don't handle 'other' methods 
2123          */
2124         if (eb->add_method) num_methods ++;
2125         if (eb->remove_method) num_methods ++;
2126         if (eb->raise_method) num_methods ++;
2127
2128         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2129         table->rows += num_methods;
2130         alloc_table (table, table->rows);
2131
2132         if (eb->add_method) {
2133                 semaidx = table->next_idx ++;
2134                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2135                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2136                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2137                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2138         }
2139         if (eb->remove_method) {
2140                 semaidx = table->next_idx ++;
2141                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2142                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2143                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2144                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2145         }
2146         if (eb->raise_method) {
2147                 semaidx = table->next_idx ++;
2148                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2149                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2150                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2151                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2152         }
2153 }
2154
2155 static void
2156 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2157 {
2158         MonoDynamicTable *table;
2159         guint32 num_constraints, i;
2160         guint32 *values;
2161         guint32 table_idx;
2162
2163         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2164         num_constraints = gparam->iface_constraints ?
2165                 mono_array_length (gparam->iface_constraints) : 0;
2166         table->rows += num_constraints;
2167         if (gparam->base_type)
2168                 table->rows++;
2169         alloc_table (table, table->rows);
2170
2171         if (gparam->base_type) {
2172                 table_idx = table->next_idx ++;
2173                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2174
2175                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2176                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2177                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2178         }
2179
2180         for (i = 0; i < num_constraints; i++) {
2181                 MonoReflectionType *constraint = mono_array_get (
2182                         gparam->iface_constraints, gpointer, i);
2183
2184                 table_idx = table->next_idx ++;
2185                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2186
2187                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2188                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2189                         assembly, mono_reflection_type_get_handle (constraint));
2190         }
2191 }
2192
2193 static void
2194 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2195 {
2196         GenericParamTableEntry *entry;
2197
2198         /*
2199          * The GenericParam table must be sorted according to the `owner' field.
2200          * We need to do this sorting prior to writing the GenericParamConstraint
2201          * table, since we have to use the final GenericParam table indices there
2202          * and they must also be sorted.
2203          */
2204
2205         entry = g_new0 (GenericParamTableEntry, 1);
2206         entry->owner = owner;
2207         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2208         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2209         entry->gparam = gparam;
2210         
2211         g_ptr_array_add (assembly->gen_params, entry);
2212 }
2213
2214 static void
2215 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2216 {
2217         MonoDynamicTable *table;
2218         MonoGenericParam *param;
2219         guint32 *values;
2220         guint32 table_idx;
2221
2222         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2223         table_idx = table->next_idx ++;
2224         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2225
2226         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2227
2228         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2229         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2230         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2231         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2232
2233         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2234
2235         encode_constraints (entry->gparam, table_idx, assembly);
2236 }
2237
2238 static guint32
2239 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2240 {
2241         MonoDynamicTable *table;
2242         guint32 token;
2243         guint32 *values;
2244         guint32 cols [MONO_ASSEMBLY_SIZE];
2245         const char *pubkey;
2246         guint32 publen;
2247
2248         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2249                 return token;
2250
2251         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2252                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2253                 token = table->next_idx ++;
2254                 table->rows ++;
2255                 alloc_table (table, table->rows);
2256                 values = table->values + token * MONO_MODULEREF_SIZE;
2257                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2258
2259                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2260                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2261                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2262
2263                 return token;
2264         }
2265         
2266         if (assembly_is_dynamic (image->assembly))
2267                 /* FIXME: */
2268                 memset (cols, 0, sizeof (cols));
2269         else {
2270                 /* image->assembly->image is the manifest module */
2271                 image = image->assembly->image;
2272                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2273         }
2274
2275         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2276         token = table->next_idx ++;
2277         table->rows ++;
2278         alloc_table (table, table->rows);
2279         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2280         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2281         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2282         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2283         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2284         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2285         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2286         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2287         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2288
2289         if (strcmp ("", image->assembly->aname.culture)) {
2290                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2291                                 image->assembly->aname.culture);
2292         }
2293
2294         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2295                 guchar pubtoken [9];
2296                 pubtoken [0] = 8;
2297                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2298                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2299         } else {
2300                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2301         }
2302         token <<= MONO_RESOLUTION_SCOPE_BITS;
2303         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2304         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2305         return token;
2306 }
2307
2308 static guint32
2309 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2310 {
2311         MonoDynamicTable *table;
2312         guint32 *values;
2313         guint32 token;
2314         SigBuffer buf;
2315
2316         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2317                 return token;
2318
2319         sigbuffer_init (&buf, 32);
2320         switch (type->type) {
2321         case MONO_TYPE_FNPTR:
2322         case MONO_TYPE_PTR:
2323         case MONO_TYPE_SZARRAY:
2324         case MONO_TYPE_ARRAY:
2325         case MONO_TYPE_VAR:
2326         case MONO_TYPE_MVAR:
2327         case MONO_TYPE_GENERICINST:
2328                 encode_type (assembly, type, &buf);
2329                 break;
2330         case MONO_TYPE_CLASS:
2331         case MONO_TYPE_VALUETYPE: {
2332                 MonoClass *k = mono_class_from_mono_type (type);
2333                 if (!k || !k->generic_container) {
2334                         sigbuffer_free (&buf);
2335                         return 0;
2336                 }
2337                 encode_type (assembly, type, &buf);
2338                 break;
2339         }
2340         default:
2341                 sigbuffer_free (&buf);
2342                 return 0;
2343         }
2344
2345         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2346         if (assembly->save) {
2347                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2348                 alloc_table (table, table->rows + 1);
2349                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2350                 values [MONO_TYPESPEC_SIGNATURE] = token;
2351         }
2352         sigbuffer_free (&buf);
2353
2354         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2355         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2356         table->next_idx ++;
2357         return token;
2358 }
2359
2360 static guint32
2361 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2362 {
2363         MonoDynamicTable *table;
2364         guint32 *values;
2365         guint32 token, scope, enclosing;
2366         MonoClass *klass;
2367
2368         /* if the type requires a typespec, we must try that first*/
2369         if (try_typespec && (token = create_typespec (assembly, type)))
2370                 return token;
2371         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2372         if (token)
2373                 return token;
2374         klass = mono_class_from_mono_type (type);
2375         if (!klass)
2376                 klass = mono_class_from_mono_type (type);
2377
2378         /*
2379          * If it's in the same module and not a generic type parameter:
2380          */
2381         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2382                         (type->type != MONO_TYPE_MVAR)) {
2383                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2384                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2385                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2386                 return token;
2387         }
2388
2389         if (klass->nested_in) {
2390                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2391                 /* get the typeref idx of the enclosing type */
2392                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2393                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2394         } else {
2395                 scope = resolution_scope_from_image (assembly, klass->image);
2396         }
2397         table = &assembly->tables [MONO_TABLE_TYPEREF];
2398         if (assembly->save) {
2399                 alloc_table (table, table->rows + 1);
2400                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2401                 values [MONO_TYPEREF_SCOPE] = scope;
2402                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2403                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2404         }
2405         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2406         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2407         table->next_idx ++;
2408         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2409         return token;
2410 }
2411
2412 /*
2413  * Despite the name, we handle also TypeSpec (with the above helper).
2414  */
2415 static guint32
2416 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2417 {
2418         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2419 }
2420
2421 #ifndef DISABLE_REFLECTION_EMIT
2422 static guint32
2423 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2424 {
2425         MonoDynamicTable *table;
2426         guint32 *values;
2427         guint32 token, pclass;
2428
2429         switch (parent & MONO_TYPEDEFORREF_MASK) {
2430         case MONO_TYPEDEFORREF_TYPEREF:
2431                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2432                 break;
2433         case MONO_TYPEDEFORREF_TYPESPEC:
2434                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2435                 break;
2436         case MONO_TYPEDEFORREF_TYPEDEF:
2437                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2438                 break;
2439         default:
2440                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2441                 return 0;
2442         }
2443         /* extract the index */
2444         parent >>= MONO_TYPEDEFORREF_BITS;
2445
2446         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2447
2448         if (assembly->save) {
2449                 alloc_table (table, table->rows + 1);
2450                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2451                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2452                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2453                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2454         }
2455
2456         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2457         table->next_idx ++;
2458
2459         return token;
2460 }
2461
2462 /*
2463  * Insert a memberef row into the metadata: the token that point to the memberref
2464  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2465  * mono_image_get_fieldref_token()).
2466  * The sig param is an index to an already built signature.
2467  */
2468 static guint32
2469 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2470 {
2471         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2472         return mono_image_add_memberef_row (assembly, parent, name, sig);
2473 }
2474
2475
2476 static guint32
2477 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2478 {
2479         guint32 token;
2480         MonoMethodSignature *sig;
2481         
2482         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2483
2484         if (create_typespec) {
2485                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2486                 if (token)
2487                         return token;
2488         } 
2489
2490         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2491         if (token && !create_typespec)
2492                 return token;
2493
2494         g_assert (!method->is_inflated);
2495         if (!token) {
2496                 /*
2497                  * A methodref signature can't contain an unmanaged calling convention.
2498                  */
2499                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2500                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2501                         sig->call_convention = MONO_CALL_DEFAULT;
2502                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2503                         method->name,  method_encode_signature (assembly, sig));
2504                 g_free (sig);
2505                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2506         }
2507
2508         if (create_typespec) {
2509                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2510                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2511                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2512
2513                 if (assembly->save) {
2514                         guint32 *values;
2515
2516                         alloc_table (table, table->rows + 1);
2517                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2518                         values [MONO_METHODSPEC_METHOD] = token;
2519                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2520                 }
2521
2522                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2523                 table->next_idx ++;
2524                 /*methodspec and memberef tokens are diferent, */
2525                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2526                 return token;
2527         }
2528         return token;
2529 }
2530
2531 static guint32
2532 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2533 {
2534         guint32 token, parent, sig;
2535         ReflectionMethodBuilder rmb;
2536         char *name;
2537         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2538         
2539         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2540         if (token)
2541                 return token;
2542
2543         name = mono_string_to_utf8 (method->name);
2544         reflection_methodbuilder_from_method_builder (&rmb, method);
2545
2546         /*
2547          * A methodref signature can't contain an unmanaged calling convention.
2548          * Since some flags are encoded as part of call_conv, we need to check against it.
2549         */
2550         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2551                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2552
2553         sig = method_builder_encode_signature (assembly, &rmb);
2554
2555         if (tb->generic_params)
2556                 parent = create_generic_typespec (assembly, tb);
2557         else
2558                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2559
2560         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2561
2562         g_free (name);
2563         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2564         return token;
2565 }
2566
2567 static guint32
2568 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2569                                      const gchar *name, guint32 sig)
2570 {
2571         MonoDynamicTable *table;
2572         guint32 token;
2573         guint32 *values;
2574         
2575         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2576
2577         if (assembly->save) {
2578                 alloc_table (table, table->rows + 1);
2579                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2580                 values [MONO_MEMBERREF_CLASS] = original;
2581                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2582                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2583         }
2584
2585         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2586         table->next_idx ++;
2587
2588         return token;
2589 }
2590
2591 static guint32
2592 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2593 {
2594         SigBuffer buf;
2595         int i;
2596         guint32 nparams = mono_array_length (mb->generic_params);
2597         guint32 idx;
2598
2599         if (!assembly->save)
2600                 return 0;
2601
2602         sigbuffer_init (&buf, 32);
2603
2604         sigbuffer_add_value (&buf, 0xa);
2605         sigbuffer_add_value (&buf, nparams);
2606
2607         for (i = 0; i < nparams; i++) {
2608                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2609                 sigbuffer_add_value (&buf, i);
2610         }
2611
2612         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2613         sigbuffer_free (&buf);
2614         return idx;
2615 }
2616
2617 static guint32
2618 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2619 {
2620         MonoDynamicTable *table;
2621         guint32 *values;
2622         guint32 token, mtoken = 0;
2623
2624         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2625         if (token)
2626                 return token;
2627
2628         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2629
2630         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2631         switch (mono_metadata_token_table (mtoken)) {
2632         case MONO_TABLE_MEMBERREF:
2633                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2634                 break;
2635         case MONO_TABLE_METHOD:
2636                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2637                 break;
2638         default:
2639                 g_assert_not_reached ();
2640         }
2641
2642         if (assembly->save) {
2643                 alloc_table (table, table->rows + 1);
2644                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2645                 values [MONO_METHODSPEC_METHOD] = mtoken;
2646                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2647         }
2648
2649         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2650         table->next_idx ++;
2651
2652         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2653         return token;
2654 }
2655
2656 static guint32
2657 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2658 {
2659         guint32 token;
2660
2661         if (mb->generic_params && create_methodspec) 
2662                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2663
2664         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2665         if (token)
2666                 return token;
2667
2668         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2669         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2670         return token;
2671 }
2672
2673 static guint32
2674 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2675 {
2676         guint32 token, parent, sig;
2677         ReflectionMethodBuilder rmb;
2678         char *name;
2679         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2680         
2681         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2682         if (token)
2683                 return token;
2684
2685         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2686
2687         if (tb->generic_params)
2688                 parent = create_generic_typespec (assembly, tb);
2689         else
2690                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2691         
2692         name = mono_string_to_utf8 (rmb.name);
2693         sig = method_builder_encode_signature (assembly, &rmb);
2694
2695         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2696
2697         g_free (name);
2698         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2699         return token;
2700 }
2701 #endif
2702
2703 static gboolean
2704 is_field_on_inst (MonoClassField *field)
2705 {
2706         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2707 }
2708
2709 /*
2710  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2711  */
2712 static MonoType*
2713 get_field_on_inst_generic_type (MonoClassField *field)
2714 {
2715         MonoClass *class, *gtd;
2716         MonoDynamicGenericClass *dgclass;
2717         int field_index;
2718
2719         g_assert (is_field_on_inst (field));
2720
2721         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2722
2723         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2724                 field_index = field - dgclass->fields;
2725                 return dgclass->field_generic_types [field_index];              
2726         }
2727
2728         class = field->parent;
2729         gtd = class->generic_class->container_class;
2730
2731         if (field >= class->fields && field - class->fields < class->field.count) {
2732                 field_index = field - class->fields;
2733                 return gtd->fields [field_index].type;
2734         }
2735
2736         g_assert_not_reached ();
2737         return 0;
2738 }
2739
2740 #ifndef DISABLE_REFLECTION_EMIT
2741 static guint32
2742 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2743 {
2744         MonoType *type;
2745         guint32 token;
2746
2747         g_assert (field);
2748         g_assert (field->parent);
2749
2750         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2751         if (token)
2752                 return token;
2753
2754         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2755                 int index = field - field->parent->fields;
2756                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2757         } else {
2758                 if (is_field_on_inst (field))
2759                         type = get_field_on_inst_generic_type (field);
2760                 else
2761                         type = mono_field_get_type (field);
2762         }
2763         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2764                                                                                         mono_field_get_name (field),
2765                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2766         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2767         return token;
2768 }
2769
2770 static guint32
2771 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2772 {
2773         guint32 token;
2774         MonoClass *klass;
2775         MonoGenericClass *gclass;
2776         MonoDynamicGenericClass *dgclass;
2777         MonoType *type;
2778         char *name;
2779
2780         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2781         if (token)
2782                 return token;
2783         if (is_sre_field_builder (mono_object_class (f->fb))) {
2784                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2785                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2786                 klass = mono_class_from_mono_type (type);
2787                 gclass = type->data.generic_class;
2788                 g_assert (gclass->is_dynamic);
2789                 dgclass = (MonoDynamicGenericClass *) gclass;
2790
2791                 name = mono_string_to_utf8 (fb->name);
2792                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2793                                                                                                 field_encode_signature (assembly, fb));
2794                 g_free (name);          
2795         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2796                 guint32 sig;
2797                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2798
2799                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2800                 klass = mono_class_from_mono_type (type);
2801
2802                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2803                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2804         } else {
2805                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2806                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2807         }
2808
2809         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2810         return token;
2811 }
2812
2813 static guint32
2814 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2815 {
2816         guint32 sig, token;
2817         MonoClass *klass;
2818         MonoGenericClass *gclass;
2819         MonoType *type;
2820
2821         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2822
2823         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2824         if (token)
2825                 return token;
2826
2827         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2828                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2829                 MonoDynamicGenericClass *dgclass;
2830                 ReflectionMethodBuilder rmb;
2831                 char *name;
2832
2833                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2834                 klass = mono_class_from_mono_type (type);
2835
2836                 gclass = type->data.generic_class;
2837                 g_assert (gclass->is_dynamic);
2838                 dgclass = (MonoDynamicGenericClass *) gclass;
2839
2840                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2841
2842                 name = mono_string_to_utf8 (rmb.name);
2843
2844                 sig = method_builder_encode_signature (assembly, &rmb);
2845
2846                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2847                 g_free (name);
2848         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2849                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2850
2851                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2852                 klass = mono_class_from_mono_type (type);
2853
2854                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2855                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2856         } else {
2857                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2858                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2859         }
2860
2861
2862         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2863         return token;
2864 }
2865
2866 static MonoMethod*
2867 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2868 {
2869         MonoClass *klass;
2870         MonoGenericContext tmp_context;
2871         MonoType **type_argv;
2872         MonoGenericInst *ginst;
2873         MonoMethod *method, *inflated;
2874         int count, i;
2875
2876         init_type_builder_generics ((MonoObject*)m->inst);
2877
2878         method = inflate_method (m->inst, (MonoObject*)m->mb);
2879
2880         klass = method->klass;
2881
2882         if (m->method_args == NULL)
2883                 return method;
2884
2885         if (method->is_inflated)
2886                 method = ((MonoMethodInflated *) method)->declaring;
2887
2888         count = mono_array_length (m->method_args);
2889
2890         type_argv = g_new0 (MonoType *, count);
2891         for (i = 0; i < count; i++) {
2892                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2893                 type_argv [i] = mono_reflection_type_get_handle (garg);
2894         }
2895         ginst = mono_metadata_get_generic_inst (count, type_argv);
2896         g_free (type_argv);
2897
2898         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2899         tmp_context.method_inst = ginst;
2900
2901         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2902         return inflated;
2903 }
2904
2905 static guint32
2906 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2907 {
2908         guint32 sig, token = 0;
2909         MonoType *type;
2910         MonoClass *klass;
2911
2912         if (m->method_args) {
2913                 MonoMethod *inflated;
2914
2915                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2916                 if (create_methodspec)
2917                         token = mono_image_get_methodspec_token (assembly, inflated);
2918                 else
2919                         token = mono_image_get_inflated_method_token (assembly, inflated);
2920                 return token;
2921         }
2922
2923         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2924         if (token)
2925                 return token;
2926
2927         if (is_sre_method_builder (mono_object_class (m->mb))) {
2928                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2929                 MonoGenericClass *gclass;
2930                 ReflectionMethodBuilder rmb;
2931                 char *name;
2932
2933                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2934                 klass = mono_class_from_mono_type (type);
2935                 gclass = type->data.generic_class;
2936                 g_assert (gclass->is_dynamic);
2937
2938                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2939
2940                 name = mono_string_to_utf8 (rmb.name);
2941
2942                 sig = method_builder_encode_signature (assembly, &rmb);
2943
2944                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2945                 g_free (name);          
2946         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2947                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2948
2949                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2950                 klass = mono_class_from_mono_type (type);
2951
2952                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2953                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2954         } else {
2955                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2956                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2957         }
2958
2959         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2960         return token;
2961 }
2962
2963 static guint32
2964 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2965 {
2966         SigBuffer buf;
2967         int i;
2968         guint32 nparams = context->method_inst->type_argc;
2969         guint32 idx;
2970
2971         if (!assembly->save)
2972                 return 0;
2973
2974         sigbuffer_init (&buf, 32);
2975         /*
2976          * FIXME: vararg, explicit_this, differenc call_conv values...
2977          */
2978         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2979         sigbuffer_add_value (&buf, nparams);
2980
2981         for (i = 0; i < nparams; i++)
2982                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2983
2984         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2985         sigbuffer_free (&buf);
2986         return idx;
2987 }
2988
2989 static guint32
2990 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2991 {
2992         MonoDynamicTable *table;
2993         guint32 *values;
2994         guint32 token, mtoken = 0, sig;
2995         MonoMethodInflated *imethod;
2996         MonoMethod *declaring;
2997
2998         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2999
3000         g_assert (method->is_inflated);
3001         imethod = (MonoMethodInflated *) method;
3002         declaring = imethod->declaring;
3003
3004         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3005         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3006
3007         if (!mono_method_signature (declaring)->generic_param_count)
3008                 return mtoken;
3009
3010         switch (mono_metadata_token_table (mtoken)) {
3011         case MONO_TABLE_MEMBERREF:
3012                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3013                 break;
3014         case MONO_TABLE_METHOD:
3015                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3016                 break;
3017         default:
3018                 g_assert_not_reached ();
3019         }
3020
3021         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3022
3023         if (assembly->save) {
3024                 alloc_table (table, table->rows + 1);
3025                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3026                 values [MONO_METHODSPEC_METHOD] = mtoken;
3027                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3028         }
3029
3030         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3031         table->next_idx ++;
3032
3033         return token;
3034 }
3035
3036 static guint32
3037 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3038 {
3039         MonoMethodInflated *imethod;
3040         guint32 token;
3041         
3042         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3043         if (token)
3044                 return token;
3045
3046         g_assert (method->is_inflated);
3047         imethod = (MonoMethodInflated *) method;
3048
3049         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3050                 token = method_encode_methodspec (assembly, method);
3051         } else {
3052                 guint32 sig = method_encode_signature (
3053                         assembly, mono_method_signature (imethod->declaring));
3054                 token = mono_image_get_memberref_token (
3055                         assembly, &method->klass->byval_arg, method->name, sig);
3056         }
3057
3058         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3059         return token;
3060 }
3061
3062 static guint32
3063 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3064 {
3065         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3066         guint32 sig, token;
3067
3068         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3069         token = mono_image_get_memberref_token (
3070                 assembly, &m->klass->byval_arg, m->name, sig);
3071
3072         return token;
3073 }
3074
3075 static guint32
3076 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3077 {
3078         MonoDynamicTable *table;
3079         MonoClass *klass;
3080         MonoType *type;
3081         guint32 *values;
3082         guint32 token;
3083         SigBuffer buf;
3084         int count, i;
3085
3086         /*
3087          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3088          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3089          * Because of this, we must not insert it into the `typeref' hash table.
3090          */
3091         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3092         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3093         if (token)
3094                 return token;
3095
3096         sigbuffer_init (&buf, 32);
3097
3098         g_assert (tb->generic_params);
3099         klass = mono_class_from_mono_type (type);
3100
3101         if (tb->generic_container)
3102                 mono_reflection_create_generic_class (tb);
3103
3104         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3105         g_assert (klass->generic_container);
3106         sigbuffer_add_value (&buf, klass->byval_arg.type);
3107         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3108
3109         count = mono_array_length (tb->generic_params);
3110         sigbuffer_add_value (&buf, count);
3111         for (i = 0; i < count; i++) {
3112                 MonoReflectionGenericParam *gparam;
3113
3114                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3115
3116                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3117         }
3118
3119         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3120
3121         if (assembly->save) {
3122                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3123                 alloc_table (table, table->rows + 1);
3124                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3125                 values [MONO_TYPESPEC_SIGNATURE] = token;
3126         }
3127         sigbuffer_free (&buf);
3128
3129         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3130         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3131         table->next_idx ++;
3132         return token;
3133 }
3134
3135 /*
3136  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3137  */
3138 static MonoType*
3139 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3140 {
3141         int i, count, len, pos;
3142         MonoType *t;
3143
3144         count = 0;
3145         if (modreq)
3146                 count += mono_array_length (modreq);
3147         if (modopt)
3148                 count += mono_array_length (modopt);
3149
3150         if (count == 0)
3151                 return mono_metadata_type_dup (NULL, type);
3152
3153         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3154         t = g_malloc (len);
3155         memcpy (t, type, MONO_SIZEOF_TYPE);
3156
3157         t->num_mods = count;
3158         pos = 0;
3159         if (modreq) {
3160                 for (i = 0; i < mono_array_length (modreq); ++i) {
3161                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3162                         t->modifiers [pos].required = 1;
3163                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3164                         pos ++;
3165                 }
3166         }
3167         if (modopt) {
3168                 for (i = 0; i < mono_array_length (modopt); ++i) {
3169                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3170                         t->modifiers [pos].required = 0;
3171                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3172                         pos ++;
3173                 }
3174         }
3175
3176         return t;
3177 }
3178
3179 static void
3180 init_type_builder_generics (MonoObject *type)
3181 {
3182         MonoReflectionTypeBuilder *tb;
3183
3184         if (!is_sre_type_builder(mono_object_class (type)))
3185                 return;
3186         tb = (MonoReflectionTypeBuilder *)type;
3187
3188         if (tb && tb->generic_container)
3189                 mono_reflection_create_generic_class (tb);
3190 }
3191
3192 static guint32
3193 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3194 {
3195         MonoDynamicTable *table;
3196         MonoClass *klass;
3197         MonoType *custom = NULL, *type;
3198         guint32 *values;
3199         guint32 token, pclass, parent, sig;
3200         gchar *name;
3201
3202         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3203         if (token)
3204                 return token;
3205
3206         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3207         name = mono_string_to_utf8 (fb->name);
3208
3209         /*FIXME this is one more layer of ugliness due how types are created.*/
3210         init_type_builder_generics (fb->type);
3211
3212         /* fb->type does not include the custom modifiers */
3213         /* FIXME: We should do this in one place when a fieldbuilder is created */
3214         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3215         if (fb->modreq || fb->modopt)
3216                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3217
3218         sig = fieldref_encode_signature (assembly, NULL, type);
3219         g_free (custom);
3220
3221         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3222         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3223         
3224         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3225         parent >>= MONO_TYPEDEFORREF_BITS;
3226
3227         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3228
3229         if (assembly->save) {
3230                 alloc_table (table, table->rows + 1);
3231                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3232                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3233                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3234                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3235         }
3236
3237         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3238         table->next_idx ++;
3239         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3240         g_free (name);
3241         return token;
3242 }
3243
3244 static guint32
3245 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3246 {
3247         SigBuffer buf;
3248         guint32 nargs;
3249         guint32 size;
3250         guint32 i, idx;
3251
3252         if (!assembly->save)
3253                 return 0;
3254
3255         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3256         g_assert (helper->type == 2);
3257
3258         if (helper->arguments)
3259                 nargs = mono_array_length (helper->arguments);
3260         else
3261                 nargs = 0;
3262
3263         size = 10 + (nargs * 10);
3264         
3265         sigbuffer_init (&buf, 32);
3266
3267         /* Encode calling convention */
3268         /* Change Any to Standard */
3269         if ((helper->call_conv & 0x03) == 0x03)
3270                 helper->call_conv = 0x01;
3271         /* explicit_this implies has_this */
3272         if (helper->call_conv & 0x40)
3273                 helper->call_conv &= 0x20;
3274
3275         if (helper->call_conv == 0) { /* Unmanaged */
3276                 idx = helper->unmanaged_call_conv - 1;
3277         } else {
3278                 /* Managed */
3279                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3280                 if (helper->call_conv & 0x02) /* varargs */
3281                         idx += 0x05;
3282         }
3283
3284         sigbuffer_add_byte (&buf, idx);
3285         sigbuffer_add_value (&buf, nargs);
3286         encode_reflection_type (assembly, helper->return_type, &buf);
3287         for (i = 0; i < nargs; ++i) {
3288                 MonoArray *modreqs = NULL;
3289                 MonoArray *modopts = NULL;
3290                 MonoReflectionType *pt;
3291
3292                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3293                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3294                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3295                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3296
3297                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3298                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3299                 encode_reflection_type (assembly, pt, &buf);
3300         }
3301         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3302         sigbuffer_free (&buf);
3303
3304         return idx;
3305 }
3306
3307 static guint32 
3308 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3309 {
3310         guint32 idx;
3311         MonoDynamicTable *table;
3312         guint32 *values;
3313
3314         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3315         idx = table->next_idx ++;
3316         table->rows ++;
3317         alloc_table (table, table->rows);
3318         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3319
3320         values [MONO_STAND_ALONE_SIGNATURE] =
3321                 mono_reflection_encode_sighelper (assembly, helper);
3322
3323         return idx;
3324 }
3325
3326 static int
3327 reflection_cc_to_file (int call_conv) {
3328         switch (call_conv & 0x3) {
3329         case 0:
3330         case 1: return MONO_CALL_DEFAULT;
3331         case 2: return MONO_CALL_VARARG;
3332         default:
3333                 g_assert_not_reached ();
3334         }
3335         return 0;
3336 }
3337 #endif /* !DISABLE_REFLECTION_EMIT */
3338
3339 typedef struct {
3340         MonoType *parent;
3341         MonoMethodSignature *sig;
3342         char *name;
3343         guint32 token;
3344 } ArrayMethod;
3345
3346 #ifndef DISABLE_REFLECTION_EMIT
3347 static guint32
3348 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3349 {
3350         guint32 nparams, i;
3351         GList *tmp;
3352         char *name;
3353         MonoMethodSignature *sig;
3354         ArrayMethod *am;
3355         MonoType *mtype;
3356
3357         name = mono_string_to_utf8 (m->name);
3358         nparams = mono_array_length (m->parameters);
3359         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3360         sig->hasthis = 1;
3361         sig->sentinelpos = -1;
3362         sig->call_convention = reflection_cc_to_file (m->call_conv);
3363         sig->param_count = nparams;
3364         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3365         mtype = mono_reflection_type_get_handle (m->parent);
3366         for (i = 0; i < nparams; ++i)
3367                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3368
3369         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3370                 am = tmp->data;
3371                 if (strcmp (name, am->name) == 0 && 
3372                                 mono_metadata_type_equal (am->parent, mtype) &&
3373                                 mono_metadata_signature_equal (am->sig, sig)) {
3374                         g_free (name);
3375                         g_free (sig);
3376                         m->table_idx = am->token & 0xffffff;
3377                         return am->token;
3378                 }
3379         }
3380         am = g_new0 (ArrayMethod, 1);
3381         am->name = name;
3382         am->sig = sig;
3383         am->parent = mtype;
3384         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3385                 method_encode_signature (assembly, sig));
3386         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3387         m->table_idx = am->token & 0xffffff;
3388         return am->token;
3389 }
3390
3391 /*
3392  * Insert into the metadata tables all the info about the TypeBuilder tb.
3393  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3394  */
3395 static void
3396 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3397 {
3398         MonoDynamicTable *table;
3399         guint *values;
3400         int i, is_object = 0, is_system = 0;
3401         char *n;
3402
3403         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3404         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3405         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3406         n = mono_string_to_utf8 (tb->name);
3407         if (strcmp (n, "Object") == 0)
3408                 is_object++;
3409         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3410         g_free (n);
3411         n = mono_string_to_utf8 (tb->nspace);
3412         if (strcmp (n, "System") == 0)
3413                 is_system++;
3414         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3415         g_free (n);
3416         if (tb->parent && !(is_system && is_object) && 
3417                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3418                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3419         } else {
3420                 values [MONO_TYPEDEF_EXTENDS] = 0;
3421         }
3422         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3423         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3424
3425         /*
3426          * if we have explicitlayout or sequentiallayouts, output data in the
3427          * ClassLayout table.
3428          */
3429         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3430                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3431                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3432                 table->rows++;
3433                 alloc_table (table, table->rows);
3434                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3435                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3436                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3437                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3438         }
3439
3440         /* handle interfaces */
3441         if (tb->interfaces) {
3442                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3443                 i = table->rows;
3444                 table->rows += mono_array_length (tb->interfaces);
3445                 alloc_table (table, table->rows);
3446                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3447                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3448                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3449                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3450                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3451                         values += MONO_INTERFACEIMPL_SIZE;
3452                 }
3453         }
3454
3455         /* handle fields */
3456         if (tb->fields) {
3457                 table = &assembly->tables [MONO_TABLE_FIELD];
3458                 table->rows += tb->num_fields;
3459                 alloc_table (table, table->rows);
3460                 for (i = 0; i < tb->num_fields; ++i)
3461                         mono_image_get_field_info (
3462                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3463         }
3464
3465         /* handle constructors */
3466         if (tb->ctors) {
3467                 table = &assembly->tables [MONO_TABLE_METHOD];
3468                 table->rows += mono_array_length (tb->ctors);
3469                 alloc_table (table, table->rows);
3470                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3471                         mono_image_get_ctor_info (domain,
3472                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3473         }
3474
3475         /* handle methods */
3476         if (tb->methods) {
3477                 table = &assembly->tables [MONO_TABLE_METHOD];
3478                 table->rows += tb->num_methods;
3479                 alloc_table (table, table->rows);
3480                 for (i = 0; i < tb->num_methods; ++i)
3481                         mono_image_get_method_info (
3482                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3483         }
3484
3485         /* Do the same with properties etc.. */
3486         if (tb->events && mono_array_length (tb->events)) {
3487                 table = &assembly->tables [MONO_TABLE_EVENT];
3488                 table->rows += mono_array_length (tb->events);
3489                 alloc_table (table, table->rows);
3490                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3491                 table->rows ++;
3492                 alloc_table (table, table->rows);
3493                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3494                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3495                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3496                 for (i = 0; i < mono_array_length (tb->events); ++i)
3497                         mono_image_get_event_info (
3498                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3499         }
3500         if (tb->properties && mono_array_length (tb->properties)) {
3501                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3502                 table->rows += mono_array_length (tb->properties);
3503                 alloc_table (table, table->rows);
3504                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3505                 table->rows ++;
3506                 alloc_table (table, table->rows);
3507                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3508                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3509                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3510                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3511                         mono_image_get_property_info (
3512                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3513         }
3514
3515         /* handle generic parameters */
3516         if (tb->generic_params) {
3517                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3518                 table->rows += mono_array_length (tb->generic_params);
3519                 alloc_table (table, table->rows);
3520                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3521                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3522
3523                         mono_image_get_generic_param_info (
3524                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3525                 }
3526         }
3527
3528         mono_image_add_decl_security (assembly, 
3529                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3530
3531         if (tb->subtypes) {
3532                 MonoDynamicTable *ntable;
3533                 
3534                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3535                 ntable->rows += mono_array_length (tb->subtypes);
3536                 alloc_table (ntable, ntable->rows);
3537                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3538
3539                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3540                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3541
3542                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3543                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3544                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3545                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3546                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3547                                 ntable->next_idx, ntable->rows);*/
3548                         values += MONO_NESTED_CLASS_SIZE;
3549                         ntable->next_idx++;
3550                 }
3551         }
3552 }
3553 #endif
3554
3555 static void
3556 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3557 {
3558         int i;
3559
3560         mono_ptr_array_append (*types, type);
3561
3562         if (!type->subtypes)
3563                 return;
3564
3565         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3566                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3567                 collect_types (types, subtype);
3568         }
3569 }
3570
3571 static gint
3572 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3573 {
3574         if ((*type1)->table_idx < (*type2)->table_idx)
3575                 return -1;
3576         else
3577                 if ((*type1)->table_idx > (*type2)->table_idx)
3578                         return 1;
3579         else
3580                 return 0;
3581 }
3582
3583 static void
3584 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3585         int i;
3586
3587         if (!pinfo)
3588                 return;
3589         for (i = 0; i < mono_array_length (pinfo); ++i) {
3590                 MonoReflectionParamBuilder *pb;
3591                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3592                 if (!pb)
3593                         continue;
3594                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3595         }
3596 }
3597
3598 static void
3599 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3600         int i;
3601         
3602         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3603         if (tb->fields) {
3604                 for (i = 0; i < tb->num_fields; ++i) {
3605                         MonoReflectionFieldBuilder* fb;
3606                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3607                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3608                 }
3609         }
3610         if (tb->events) {
3611                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3612                         MonoReflectionEventBuilder* eb;
3613                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3614                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3615                 }
3616         }
3617         if (tb->properties) {
3618                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3619                         MonoReflectionPropertyBuilder* pb;
3620                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3621                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3622                 }
3623         }
3624         if (tb->ctors) {
3625                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3626                         MonoReflectionCtorBuilder* cb;
3627                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3628                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3629                         params_add_cattrs (assembly, cb->pinfo);
3630                 }
3631         }
3632
3633         if (tb->methods) {
3634                 for (i = 0; i < tb->num_methods; ++i) {
3635                         MonoReflectionMethodBuilder* mb;
3636                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3637                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3638                         params_add_cattrs (assembly, mb->pinfo);
3639                 }
3640         }
3641
3642         if (tb->subtypes) {
3643                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3644                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3645         }
3646 }
3647
3648 static void
3649 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3650 {
3651         int i;
3652         
3653         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3654
3655         if (moduleb->global_methods) {
3656                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3657                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3658                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3659                         params_add_cattrs (assembly, mb->pinfo);
3660                 }
3661         }
3662
3663         if (moduleb->global_fields) {
3664                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3665                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3666                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3667                 }
3668         }
3669         
3670         if (moduleb->types) {
3671                 for (i = 0; i < moduleb->num_types; ++i)
3672                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3673         }
3674 }
3675
3676 static void
3677 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3678 {
3679         MonoDynamicTable *table;
3680         guint32 *values;
3681         char blob_size [6];
3682         guchar hash [20];
3683         char *b = blob_size;
3684         char *dir, *path;
3685
3686         table = &assembly->tables [MONO_TABLE_FILE];
3687         table->rows++;
3688         alloc_table (table, table->rows);
3689         values = table->values + table->next_idx * MONO_FILE_SIZE;
3690         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3691         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3692         if (image_is_dynamic (module->image)) {
3693                 /* This depends on the fact that the main module is emitted last */
3694                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3695                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3696         } else {
3697                 dir = NULL;
3698                 path = g_strdup (module->image->name);
3699         }
3700         mono_sha1_get_digest_from_file (path, hash);
3701         g_free (dir);
3702         g_free (path);
3703         mono_metadata_encode_value (20, b, &b);
3704         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3705         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3706         table->next_idx ++;
3707 }
3708
3709 static void
3710 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3711 {
3712         MonoDynamicTable *table;
3713         int i;
3714
3715         table = &assembly->tables [MONO_TABLE_MODULE];
3716         mb->table_idx = table->next_idx ++;
3717         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3718         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3719         i /= 16;
3720         ++i;
3721         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3722         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3723         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3724         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3725 }
3726
3727 static guint32
3728 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3729         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3730 {
3731         MonoDynamicTable *table;
3732         guint32 *values;
3733         guint32 visib, res;
3734
3735         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3736         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3737                 return 0;
3738
3739         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3740         table->rows++;
3741         alloc_table (table, table->rows);
3742         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3743
3744         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3745         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3746         if (klass->nested_in)
3747                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3748         else
3749                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3750         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3751         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3752
3753         res = table->next_idx;
3754
3755         table->next_idx ++;
3756
3757         /* Emit nested types */
3758         if (klass->ext && klass->ext->nested_classes) {
3759                 GList *tmp;
3760
3761                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3762                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3763         }
3764
3765         return res;
3766 }
3767
3768 static void
3769 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3770         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3771 {
3772         MonoClass *klass;
3773         guint32 idx, i;
3774
3775         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3776
3777         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3778
3779         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3780                                                                                                    parent_index, assembly);
3781
3782         /* 
3783          * Emit nested types
3784          * We need to do this ourselves since klass->nested_classes is not set up.
3785          */
3786         if (tb->subtypes) {
3787                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3788                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3789         }
3790 }
3791
3792 static void
3793 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3794         guint32 module_index, MonoDynamicImage *assembly)
3795 {
3796         MonoImage *image = module->image;
3797         MonoTableInfo  *t;
3798         guint32 i;
3799
3800         t = &image->tables [MONO_TABLE_TYPEDEF];
3801
3802         for (i = 0; i < t->rows; ++i) {
3803                 MonoError error;
3804                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3805                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3806
3807                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3808                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3809         }
3810 }
3811
3812 static void
3813 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3814 {
3815         MonoDynamicTable *table;
3816         guint32 *values;
3817         guint32 scope, scope_idx, impl, current_idx;
3818         gboolean forwarder = TRUE;
3819         gpointer iter = NULL;
3820         MonoClass *nested;
3821
3822         if (klass->nested_in) {
3823                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3824                 forwarder = FALSE;
3825         } else {
3826                 scope = resolution_scope_from_image (assembly, klass->image);
3827                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
3828                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
3829                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3830         }
3831
3832         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3833
3834         table->rows++;
3835         alloc_table (table, table->rows);
3836         current_idx = table->next_idx;
3837         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3838
3839         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3840         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3841         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3842         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3843         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3844
3845         table->next_idx++;
3846
3847         while ((nested = mono_class_get_nested_types (klass, &iter)))
3848                 add_exported_type (assemblyb, assembly, nested, current_idx);
3849 }
3850
3851 static void
3852 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3853 {
3854         MonoClass *klass;
3855         int i;
3856
3857         if (!assemblyb->type_forwarders)
3858                 return;
3859
3860         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3861                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3862                 MonoType *type;
3863                 if (!t)
3864                         continue;
3865
3866                 type = mono_reflection_type_get_handle (t);
3867                 g_assert (type);
3868
3869                 klass = mono_class_from_mono_type (type);
3870
3871                 add_exported_type (assemblyb, assembly, klass, 0);
3872         }
3873 }
3874
3875 #define align_pointer(base,p)\
3876         do {\
3877                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3878                 if (__diff & 3)\
3879                         (p) += 4 - (__diff & 3);\
3880         } while (0)
3881
3882 static int
3883 compare_constants (const void *a, const void *b)
3884 {
3885         const guint32 *a_values = a;
3886         const guint32 *b_values = b;
3887         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3888 }
3889
3890 static int
3891 compare_semantics (const void *a, const void *b)
3892 {
3893         const guint32 *a_values = a;
3894         const guint32 *b_values = b;
3895         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3896         if (assoc)
3897                 return assoc;
3898         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3899 }
3900
3901 static int
3902 compare_custom_attrs (const void *a, const void *b)
3903 {
3904         const guint32 *a_values = a;
3905         const guint32 *b_values = b;
3906
3907         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3908 }
3909
3910 static int
3911 compare_field_marshal (const void *a, const void *b)
3912 {
3913         const guint32 *a_values = a;
3914         const guint32 *b_values = b;
3915
3916         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3917 }
3918
3919 static int
3920 compare_nested (const void *a, const void *b)
3921 {
3922         const guint32 *a_values = a;
3923         const guint32 *b_values = b;
3924
3925         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3926 }
3927
3928 static int
3929 compare_genericparam (const void *a, const void *b)
3930 {
3931         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3932         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3933
3934         if ((*b_entry)->owner == (*a_entry)->owner)
3935                 return 
3936                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3937                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3938         else
3939                 return (*a_entry)->owner - (*b_entry)->owner;
3940 }
3941
3942 static int
3943 compare_declsecurity_attrs (const void *a, const void *b)
3944 {
3945         const guint32 *a_values = a;
3946         const guint32 *b_values = b;
3947
3948         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3949 }
3950
3951 static int
3952 compare_interface_impl (const void *a, const void *b)
3953 {
3954         const guint32 *a_values = a;
3955         const guint32 *b_values = b;
3956
3957         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3958         if (klass)
3959                 return klass;
3960
3961         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3962 }
3963
3964 static void
3965 pad_heap (MonoDynamicStream *sh)
3966 {
3967         if (sh->index & 3) {
3968                 int sz = 4 - (sh->index & 3);
3969                 memset (sh->data + sh->index, 0, sz);
3970                 sh->index += sz;
3971         }
3972 }
3973
3974 struct StreamDesc {
3975         const char *name;
3976         MonoDynamicStream *stream;
3977 };
3978
3979 /*
3980  * build_compressed_metadata() fills in the blob of data that represents the 
3981  * raw metadata as it will be saved in the PE file. The five streams are output 
3982  * and the metadata tables are comnpressed from the guint32 array representation, 
3983  * to the compressed on-disk format.
3984  */
3985 static void
3986 build_compressed_metadata (MonoDynamicImage *assembly)
3987 {
3988         MonoDynamicTable *table;
3989         int i;
3990         guint64 valid_mask = 0;
3991         guint64 sorted_mask;
3992         guint32 heapt_size = 0;
3993         guint32 meta_size = 256; /* allow for header and other stuff */
3994         guint32 table_offset;
3995         guint32 ntables = 0;
3996         guint64 *int64val;
3997         guint32 *int32val;
3998         guint16 *int16val;
3999         MonoImage *meta;
4000         unsigned char *p;
4001         struct StreamDesc stream_desc [5];
4002
4003         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4004         for (i = 0; i < assembly->gen_params->len; i++){
4005                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4006                 write_generic_param_entry (assembly, entry);
4007         }
4008
4009         stream_desc [0].name  = "#~";
4010         stream_desc [0].stream = &assembly->tstream;
4011         stream_desc [1].name  = "#Strings";
4012         stream_desc [1].stream = &assembly->sheap;
4013         stream_desc [2].name  = "#US";
4014         stream_desc [2].stream = &assembly->us;
4015         stream_desc [3].name  = "#Blob";
4016         stream_desc [3].stream = &assembly->blob;
4017         stream_desc [4].name  = "#GUID";
4018         stream_desc [4].stream = &assembly->guid;
4019         
4020         /* tables that are sorted */
4021         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4022                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4023                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4024                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4025                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4026                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4027                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4028         
4029         /* Compute table sizes */
4030         /* the MonoImage has already been created in mono_image_basic_init() */
4031         meta = &assembly->image;
4032
4033         /* sizes should be multiple of 4 */
4034         pad_heap (&assembly->blob);
4035         pad_heap (&assembly->guid);
4036         pad_heap (&assembly->sheap);
4037         pad_heap (&assembly->us);
4038
4039         /* Setup the info used by compute_sizes () */
4040         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4041         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4042         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4043
4044         meta_size += assembly->blob.index;
4045         meta_size += assembly->guid.index;
4046         meta_size += assembly->sheap.index;
4047         meta_size += assembly->us.index;
4048
4049         for (i=0; i < MONO_TABLE_NUM; ++i)
4050                 meta->tables [i].rows = assembly->tables [i].rows;
4051         
4052         for (i = 0; i < MONO_TABLE_NUM; i++){
4053                 if (meta->tables [i].rows == 0)
4054                         continue;
4055                 valid_mask |= (guint64)1 << i;
4056                 ntables ++;
4057                 meta->tables [i].row_size = mono_metadata_compute_size (
4058                         meta, i, &meta->tables [i].size_bitfield);
4059                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4060         }
4061         heapt_size += 24; /* #~ header size */
4062         heapt_size += ntables * 4;
4063         /* make multiple of 4 */
4064         heapt_size += 3;
4065         heapt_size &= ~3;
4066         meta_size += heapt_size;
4067         meta->raw_metadata = g_malloc0 (meta_size);
4068         p = (unsigned char*)meta->raw_metadata;
4069         /* the metadata signature */
4070         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4071         /* version numbers and 4 bytes reserved */
4072         int16val = (guint16*)p;
4073         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4074         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4075         p += 8;
4076         /* version string */
4077         int32val = (guint32*)p;
4078         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4079         p += 4;
4080         memcpy (p, meta->version, strlen (meta->version));
4081         p += GUINT32_FROM_LE (*int32val);
4082         align_pointer (meta->raw_metadata, p);
4083         int16val = (guint16*)p;
4084         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4085         *int16val = GUINT16_TO_LE (5); /* number of streams */
4086         p += 4;
4087
4088         /*
4089          * write the stream info.
4090          */
4091         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4092         table_offset += 3; table_offset &= ~3;
4093
4094         assembly->tstream.index = heapt_size;
4095         for (i = 0; i < 5; ++i) {
4096                 int32val = (guint32*)p;
4097                 stream_desc [i].stream->offset = table_offset;
4098                 *int32val++ = GUINT32_TO_LE (table_offset);
4099                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4100                 table_offset += GUINT32_FROM_LE (*int32val);
4101                 table_offset += 3; table_offset &= ~3;
4102                 p += 8;
4103                 strcpy ((char*)p, stream_desc [i].name);
4104                 p += strlen (stream_desc [i].name) + 1;
4105                 align_pointer (meta->raw_metadata, p);
4106         }
4107         /* 
4108          * now copy the data, the table stream header and contents goes first.
4109          */
4110         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4111         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4112         int32val = (guint32*)p;
4113         *int32val = GUINT32_TO_LE (0); /* reserved */
4114         p += 4;
4115
4116         *p++ = 2; /* version */
4117         *p++ = 0;
4118
4119         if (meta->idx_string_wide)
4120                 *p |= 0x01;
4121         if (meta->idx_guid_wide)
4122                 *p |= 0x02;
4123         if (meta->idx_blob_wide)
4124                 *p |= 0x04;
4125         ++p;
4126         *p++ = 1; /* reserved */
4127         int64val = (guint64*)p;
4128         *int64val++ = GUINT64_TO_LE (valid_mask);
4129         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4130         p += 16;
4131         int32val = (guint32*)p;
4132         for (i = 0; i < MONO_TABLE_NUM; i++){
4133                 if (meta->tables [i].rows == 0)
4134                         continue;
4135                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4136         }
4137         p = (unsigned char*)int32val;
4138
4139         /* sort the tables that still need sorting */
4140         table = &assembly->tables [MONO_TABLE_CONSTANT];
4141         if (table->rows)
4142                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4143         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4144         if (table->rows)
4145                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4146         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4147         if (table->rows)
4148                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4149         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4150         if (table->rows)
4151                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4152         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4153         if (table->rows)
4154                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4155         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4156         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4157         if (table->rows)
4158                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4159         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4160         if (table->rows)
4161                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4162
4163         /* compress the tables */
4164         for (i = 0; i < MONO_TABLE_NUM; i++){
4165                 int row, col;
4166                 guint32 *values;
4167                 guint32 bitfield = meta->tables [i].size_bitfield;
4168                 if (!meta->tables [i].rows)
4169                         continue;
4170                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4171                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4172                 meta->tables [i].base = (char*)p;
4173                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4174                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4175                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4176                                 switch (mono_metadata_table_size (bitfield, col)) {
4177                                 case 1:
4178                                         *p++ = values [col];
4179                                         break;
4180                                 case 2:
4181                                         *p++ = values [col] & 0xff;
4182                                         *p++ = (values [col] >> 8) & 0xff;
4183                                         break;
4184                                 case 4:
4185                                         *p++ = values [col] & 0xff;
4186                                         *p++ = (values [col] >> 8) & 0xff;
4187                                         *p++ = (values [col] >> 16) & 0xff;
4188                                         *p++ = (values [col] >> 24) & 0xff;
4189                                         break;
4190                                 default:
4191                                         g_assert_not_reached ();
4192                                 }
4193                         }
4194                 }
4195                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4196         }
4197         
4198         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4199         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4200         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4201         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4202         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4203
4204         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4205 }
4206
4207 /*
4208  * Some tables in metadata need to be sorted according to some criteria, but
4209  * when methods and fields are first created with reflection, they may be assigned a token
4210  * that doesn't correspond to the final token they will get assigned after the sorting.
4211  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4212  * with the reflection objects that represent them. Once all the tables are set up, the 
4213  * reflection objects will contains the correct table index. fixup_method() will fixup the
4214  * tokens for the method with ILGenerator @ilgen.
4215  */
4216 static void
4217 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4218 {
4219         guint32 code_idx = GPOINTER_TO_UINT (value);
4220         MonoReflectionILTokenInfo *iltoken;
4221         MonoReflectionFieldBuilder *field;
4222         MonoReflectionCtorBuilder *ctor;
4223         MonoReflectionMethodBuilder *method;
4224         MonoReflectionTypeBuilder *tb;
4225         MonoReflectionArrayMethod *am;
4226         guint32 i, idx = 0;
4227         unsigned char *target;
4228
4229         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4230                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4231                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4232                 switch (target [3]) {
4233                 case MONO_TABLE_FIELD:
4234                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4235                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4236                                 idx = field->table_idx;
4237                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4238                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4239                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4240                         } else {
4241                                 g_assert_not_reached ();
4242                         }
4243                         break;
4244                 case MONO_TABLE_METHOD:
4245                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4246                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4247                                 idx = method->table_idx;
4248                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4249                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4250                                 idx = ctor->table_idx;
4251                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4252                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4253                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4254                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4255                         } else {
4256                                 g_assert_not_reached ();
4257                         }
4258                         break;
4259                 case MONO_TABLE_TYPEDEF:
4260                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4261                                 g_assert_not_reached ();
4262                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4263                         idx = tb->table_idx;
4264                         break;
4265                 case MONO_TABLE_MEMBERREF:
4266                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4267                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4268                                 idx = am->table_idx;
4269                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4270                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4271                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4272                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4273                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4274                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4275                                 continue;
4276                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4277                                 continue;
4278                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4279                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4280                                 g_assert (is_field_on_inst (f));
4281                                 continue;
4282                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4283                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4288                                 continue;
4289                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4290                                 continue;
4291                         } else {
4292                                 g_assert_not_reached ();
4293                         }
4294                         break;
4295                 case MONO_TABLE_METHODSPEC:
4296                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4297                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4298                                 g_assert (mono_method_signature (m)->generic_param_count);
4299                                 continue;
4300                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4301                                 continue;
4302                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4303                                 continue;
4304                         } else {
4305                                 g_assert_not_reached ();
4306                         }
4307                         break;
4308                 default:
4309                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4310                 }
4311                 target [0] = idx & 0xff;
4312                 target [1] = (idx >> 8) & 0xff;
4313                 target [2] = (idx >> 16) & 0xff;
4314         }
4315 }
4316
4317 /*
4318  * fixup_cattrs:
4319  *
4320  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4321  * value is not known when the table is emitted.
4322  */
4323 static void
4324 fixup_cattrs (MonoDynamicImage *assembly)
4325 {
4326         MonoDynamicTable *table;
4327         guint32 *values;
4328         guint32 type, i, idx, token;
4329         MonoObject *ctor;
4330
4331         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4332
4333         for (i = 0; i < table->rows; ++i) {
4334                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4335
4336                 type = values [MONO_CUSTOM_ATTR_TYPE];
4337                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4338                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4339                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4340                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4341                         g_assert (ctor);
4342
4343                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4344                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4345                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4346                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4347                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4348                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4349                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4350                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4351                         }
4352                 }
4353         }
4354 }
4355
4356 static void
4357 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4358 {
4359         MonoDynamicTable *table;
4360         guint32 *values;
4361
4362         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4363         table->rows++;
4364         alloc_table (table, table->rows);
4365         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4366         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4367         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4368         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4369         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4370         table->next_idx++;
4371 }
4372
4373 static void
4374 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4375 {
4376         MonoDynamicTable *table;
4377         guint32 *values;
4378         char blob_size [6];
4379         guchar hash [20];
4380         char *b = blob_size;
4381         char *name, *sname;
4382         guint32 idx, offset;
4383
4384         if (rsrc->filename) {
4385                 name = mono_string_to_utf8 (rsrc->filename);
4386                 sname = g_path_get_basename (name);
4387         
4388                 table = &assembly->tables [MONO_TABLE_FILE];
4389                 table->rows++;
4390                 alloc_table (table, table->rows);
4391                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4392                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4393                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4394                 g_free (sname);
4395
4396                 mono_sha1_get_digest_from_file (name, hash);
4397                 mono_metadata_encode_value (20, b, &b);
4398                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4399                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4400                 g_free (name);
4401                 idx = table->next_idx++;
4402                 rsrc->offset = 0;
4403                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4404         } else {
4405                 char sizebuf [4];
4406                 char *data;
4407                 guint len;
4408                 if (rsrc->data) {
4409                         data = mono_array_addr (rsrc->data, char, 0);
4410                         len = mono_array_length (rsrc->data);
4411                 } else {
4412                         data = NULL;
4413                         len = 0;
4414                 }
4415                 offset = len;
4416                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4417                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4418                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4419                 mono_image_add_stream_data (&assembly->resources, data, len);
4420
4421                 if (!mb->is_main)
4422                         /* 
4423                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4424                          * the main module, but that needs to reference the FILE table
4425                          * which isn't emitted yet.
4426                          */
4427                         return;
4428                 else
4429                         idx = 0;
4430         }
4431
4432         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4433 }
4434
4435 static void
4436 set_version_from_string (MonoString *version, guint32 *values)
4437 {
4438         gchar *ver, *p, *str;
4439         guint32 i;
4440         
4441         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4442         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4443         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4444         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4445         if (!version)
4446                 return;
4447         ver = str = mono_string_to_utf8 (version);
4448         for (i = 0; i < 4; ++i) {
4449                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4450                 switch (*p) {
4451                 case '.':
4452                         p++;
4453                         break;
4454                 case '*':
4455                         /* handle Revision and Build */
4456                         p++;
4457                         break;
4458                 }
4459                 ver = p;
4460         }
4461         g_free (str);
4462 }
4463
4464 static guint32
4465 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4466         gsize len;
4467         guint32 token = 0;
4468         char blob_size [6];
4469         char *b = blob_size;
4470
4471         if (!pkey)
4472                 return token;
4473
4474         len = mono_array_length (pkey);
4475         mono_metadata_encode_value (len, b, &b);
4476         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4477         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4478
4479         assembly->public_key = g_malloc (len);
4480         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4481         assembly->public_key_len = len;
4482
4483         /* Special case: check for ECMA key (16 bytes) */
4484         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4485                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4486                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4487         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4488                 /* minimum key size (in 2.0) is 384 bits */
4489                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4490         } else {
4491                 /* FIXME - verifier */
4492                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4493                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4494         }
4495         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4496
4497         return token;
4498 }
4499
4500 static void
4501 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4502 {
4503         MonoDynamicTable *table;
4504         MonoDynamicImage *assembly;
4505         MonoReflectionAssemblyBuilder *assemblyb;
4506         MonoDomain *domain;
4507         guint32 *values;
4508         int i;
4509         guint32 module_index;
4510
4511         assemblyb = moduleb->assemblyb;
4512         assembly = moduleb->dynamic_image;
4513         domain = mono_object_domain (assemblyb);
4514
4515         /* Emit ASSEMBLY table */
4516         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4517         alloc_table (table, 1);
4518         values = table->values + MONO_ASSEMBLY_SIZE;
4519         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4520         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4521         if (assemblyb->culture) {
4522                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4523         } else {
4524                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4525         }
4526         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4527         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4528         set_version_from_string (assemblyb->version, values);
4529
4530         /* Emit FILE + EXPORTED_TYPE table */
4531         module_index = 0;
4532         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4533                 int j;
4534                 MonoReflectionModuleBuilder *file_module = 
4535                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4536                 if (file_module != moduleb) {
4537                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4538                         module_index ++;
4539                         if (file_module->types) {
4540                                 for (j = 0; j < file_module->num_types; ++j) {
4541                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4542                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4543                                 }
4544                         }
4545                 }
4546         }
4547         if (assemblyb->loaded_modules) {
4548                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4549                         MonoReflectionModule *file_module = 
4550                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4551                         mono_image_fill_file_table (domain, file_module, assembly);
4552                         module_index ++;
4553                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4554                 }
4555         }
4556         if (assemblyb->type_forwarders)
4557                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4558
4559         /* Emit MANIFESTRESOURCE table */
4560         module_index = 0;
4561         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4562                 int j;
4563                 MonoReflectionModuleBuilder *file_module = 
4564                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4565                 /* The table for the main module is emitted later */
4566                 if (file_module != moduleb) {
4567                         module_index ++;
4568                         if (file_module->resources) {
4569                                 int len = mono_array_length (file_module->resources);
4570                                 for (j = 0; j < len; ++j) {
4571                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4572                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4573                                 }
4574                         }
4575                 }
4576         }               
4577 }
4578
4579 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4580
4581 /*
4582  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4583  * for the modulebuilder @moduleb.
4584  * At the end of the process, method and field tokens are fixed up and the 
4585  * on-disk compressed metadata representation is created.
4586  */
4587 void
4588 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4589 {
4590         MonoDynamicTable *table;
4591         MonoDynamicImage *assembly;
4592         MonoReflectionAssemblyBuilder *assemblyb;
4593         MonoDomain *domain;
4594         MonoPtrArray types;
4595         guint32 *values;
4596         int i, j;
4597
4598         assemblyb = moduleb->assemblyb;
4599         assembly = moduleb->dynamic_image;
4600         domain = mono_object_domain (assemblyb);
4601
4602         if (assembly->text_rva)
4603                 return;
4604
4605         assembly->text_rva = START_TEXT_RVA;
4606
4607         if (moduleb->is_main) {
4608                 mono_image_emit_manifest (moduleb);
4609         }
4610
4611         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4612         table->rows = 1; /* .<Module> */
4613         table->next_idx++;
4614         alloc_table (table, table->rows);
4615         /*
4616          * Set the first entry.
4617          */
4618         values = table->values + table->columns;
4619         values [MONO_TYPEDEF_FLAGS] = 0;
4620         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4621         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4622         values [MONO_TYPEDEF_EXTENDS] = 0;
4623         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4624         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4625
4626         /* 
4627          * handle global methods 
4628          * FIXME: test what to do when global methods are defined in multiple modules.
4629          */
4630         if (moduleb->global_methods) {
4631                 table = &assembly->tables [MONO_TABLE_METHOD];
4632                 table->rows += mono_array_length (moduleb->global_methods);
4633                 alloc_table (table, table->rows);
4634                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4635                         mono_image_get_method_info (
4636                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4637         }
4638         if (moduleb->global_fields) {
4639                 table = &assembly->tables [MONO_TABLE_FIELD];
4640                 table->rows += mono_array_length (moduleb->global_fields);
4641                 alloc_table (table, table->rows);
4642                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4643                         mono_image_get_field_info (
4644                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4645         }
4646
4647         table = &assembly->tables [MONO_TABLE_MODULE];
4648         alloc_table (table, 1);
4649         mono_image_fill_module_table (domain, moduleb, assembly);
4650
4651         /* Collect all types into a list sorted by their table_idx */
4652         mono_ptr_array_init (types, moduleb->num_types);
4653
4654         if (moduleb->types)
4655                 for (i = 0; i < moduleb->num_types; ++i) {
4656                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4657                         collect_types (&types, type);
4658                 }
4659
4660         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4661         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4662         table->rows += mono_ptr_array_size (types);
4663         alloc_table (table, table->rows);
4664
4665         /*
4666          * Emit type names + namespaces at one place inside the string heap,
4667          * so load_class_names () needs to touch fewer pages.
4668          */
4669         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4670                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4671                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4672         }
4673         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4674                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4675                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4676         }
4677
4678         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4679                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4680                 mono_image_get_type_info (domain, type, assembly);
4681         }
4682
4683         /* 
4684          * table->rows is already set above and in mono_image_fill_module_table.
4685          */
4686         /* add all the custom attributes at the end, once all the indexes are stable */
4687         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4688
4689         /* CAS assembly permissions */
4690         if (assemblyb->permissions_minimum)
4691                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4692         if (assemblyb->permissions_optional)
4693                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4694         if (assemblyb->permissions_refused)
4695                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4696
4697         module_add_cattrs (assembly, moduleb);
4698
4699         /* fixup tokens */
4700         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4701
4702         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4703          * the final tokens and don't need another fixup pass. */
4704
4705         if (moduleb->global_methods) {
4706                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4707                         MonoReflectionMethodBuilder *mb = mono_array_get (
4708                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4709                         mono_image_add_methodimpl (assembly, mb);
4710                 }
4711         }
4712
4713         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4714                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4715                 if (type->methods) {
4716                         for (j = 0; j < type->num_methods; ++j) {
4717                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4718                                         type->methods, MonoReflectionMethodBuilder*, j);
4719
4720                                 mono_image_add_methodimpl (assembly, mb);
4721                         }
4722                 }
4723         }
4724
4725         mono_ptr_array_destroy (types);
4726
4727         fixup_cattrs (assembly);
4728 }
4729
4730 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4731
4732 void
4733 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4734 {
4735         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4736 }
4737
4738 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4739
4740
4741 typedef struct {
4742         guint32 import_lookup_table;
4743         guint32 timestamp;
4744         guint32 forwarder;
4745         guint32 name_rva;
4746         guint32 import_address_table_rva;
4747 } MonoIDT;
4748
4749 typedef struct {
4750         guint32 name_rva;
4751         guint32 flags;
4752 } MonoILT;
4753
4754 #ifndef DISABLE_REFLECTION_EMIT
4755
4756 /*
4757  * mono_image_insert_string:
4758  * @module: module builder object
4759  * @str: a string
4760  *
4761  * Insert @str into the user string stream of @module.
4762  */
4763 guint32
4764 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4765 {
4766         MonoDynamicImage *assembly;
4767         guint32 idx;
4768         char buf [16];
4769         char *b = buf;
4770         
4771         MONO_ARCH_SAVE_REGS;
4772
4773         if (!module->dynamic_image)
4774                 mono_image_module_basic_init (module);
4775
4776         assembly = module->dynamic_image;
4777         
4778         if (assembly->save) {
4779                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4780                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4781 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4782         {
4783                 char *swapped = g_malloc (2 * mono_string_length (str));
4784                 const char *p = (const char*)mono_string_chars (str);
4785
4786                 swap_with_size (swapped, p, 2, mono_string_length (str));
4787                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4788                 g_free (swapped);
4789         }
4790 #else
4791                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4792 #endif
4793                 mono_image_add_stream_data (&assembly->us, "", 1);
4794         } else {
4795                 idx = assembly->us.index ++;
4796         }
4797
4798         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4799
4800         return MONO_TOKEN_STRING | idx;
4801 }
4802
4803 guint32
4804 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4805 {
4806         MonoClass *klass;
4807         guint32 token = 0;
4808         MonoMethodSignature *sig;
4809
4810         klass = obj->vtable->klass;
4811         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4812                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4813                 MonoMethodSignature *old;
4814                 guint32 sig_token, parent;
4815                 int nargs, i;
4816
4817                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4818
4819                 nargs = mono_array_length (opt_param_types);
4820                 old = mono_method_signature (method);
4821                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4822
4823                 sig->hasthis = old->hasthis;
4824                 sig->explicit_this = old->explicit_this;
4825                 sig->call_convention = old->call_convention;
4826                 sig->generic_param_count = old->generic_param_count;
4827                 sig->param_count = old->param_count + nargs;
4828                 sig->sentinelpos = old->param_count;
4829                 sig->ret = old->ret;
4830
4831                 for (i = 0; i < old->param_count; i++)
4832                         sig->params [i] = old->params [i];
4833
4834                 for (i = 0; i < nargs; i++) {
4835                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4836                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4837                 }
4838
4839                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4840                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4841                 parent >>= MONO_TYPEDEFORREF_BITS;
4842
4843                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4844                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4845
4846                 sig_token = method_encode_signature (assembly, sig);
4847                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4848         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4849                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4850                 ReflectionMethodBuilder rmb;
4851                 guint32 parent, sig_token;
4852                 int nopt_args, nparams, ngparams, i;
4853                 char *name;
4854
4855                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4856                 rmb.opt_types = opt_param_types;
4857                 nopt_args = mono_array_length (opt_param_types);
4858
4859                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4860                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4861                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4862
4863                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4864                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4865                 sig->call_convention = rmb.call_conv;
4866                 sig->generic_param_count = ngparams;
4867                 sig->param_count = nparams + nopt_args;
4868                 sig->sentinelpos = nparams;
4869                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4870
4871                 for (i = 0; i < nparams; i++) {
4872                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4873                         sig->params [i] = mono_reflection_type_get_handle (rt);
4874                 }
4875
4876                 for (i = 0; i < nopt_args; i++) {
4877                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4878                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4879                 }
4880
4881                 sig_token = method_builder_encode_signature (assembly, &rmb);
4882
4883                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4884                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4885
4886                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4887                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4888
4889                 name = mono_string_to_utf8 (rmb.name);
4890                 token = mono_image_get_varargs_method_token (
4891                         assembly, parent, name, sig_token);
4892                 g_free (name);
4893         } else {
4894                 g_error ("requested method token for %s\n", klass->name);
4895         }
4896
4897         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4898         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4899         return token;
4900 }
4901
4902 /*
4903  * mono_image_create_token:
4904  * @assembly: a dynamic assembly
4905  * @obj:
4906  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4907  *
4908  * Get a token to insert in the IL code stream for the given MemberInfo.
4909  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4910  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4911  * entry.
4912  */
4913 guint32
4914 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4915                                                  gboolean create_open_instance, gboolean register_token)
4916 {
4917         MonoClass *klass;
4918         guint32 token = 0;
4919
4920         klass = obj->vtable->klass;
4921
4922         /* Check for user defined reflection objects */
4923         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4924         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4925                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4926
4927         if (strcmp (klass->name, "MethodBuilder") == 0) {
4928                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4929                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4930
4931                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4932                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4933                 else
4934                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4935                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4936         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4937                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4938                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4939
4940                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4941                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4942                 else
4943                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4944                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4945         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4946                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4947                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4948                 if (tb->generic_params) {
4949                         token = mono_image_get_generic_field_token (assembly, fb);
4950                 } else {
4951                         if (tb->module->dynamic_image == assembly) {
4952                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4953                         } else {
4954                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4955                         }
4956                 }
4957         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4958                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4959                 if (create_open_instance && tb->generic_params) {
4960                         MonoType *type;
4961                         init_type_builder_generics (obj);
4962                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4963                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4964                         token = mono_metadata_token_from_dor (token);
4965                 } else if (tb->module->dynamic_image == assembly) {
4966                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4967                 } else {
4968                         MonoType *type;
4969                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4970                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4971                 }
4972         } else if (strcmp (klass->name, "MonoType") == 0) {
4973                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4974                 MonoClass *mc = mono_class_from_mono_type (type);
4975                 token = mono_metadata_token_from_dor (
4976                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4977         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4978                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979                 token = mono_metadata_token_from_dor (
4980                         mono_image_typedef_or_ref (assembly, type));
4981         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4982                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4983                 token = mono_metadata_token_from_dor (
4984                         mono_image_typedef_or_ref (assembly, type));
4985         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4986                    strcmp (klass->name, "MonoMethod") == 0 ||
4987                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4988                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4989                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4990                 if (m->method->is_inflated) {
4991                         if (create_open_instance)
4992                                 token = mono_image_get_methodspec_token (assembly, m->method);
4993                         else
4994                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4995                 } else if ((m->method->klass->image == &assembly->image) &&
4996                          !m->method->klass->generic_class) {
4997                         static guint32 method_table_idx = 0xffffff;
4998                         if (m->method->klass->wastypebuilder) {
4999                                 /* we use the same token as the one that was assigned
5000                                  * to the Methodbuilder.
5001                                  * FIXME: do the equivalent for Fields.
5002                                  */
5003                                 token = m->method->token;
5004                         } else {
5005                                 /*
5006                                  * Each token should have a unique index, but the indexes are
5007                                  * assigned by managed code, so we don't know about them. An
5008                                  * easy solution is to count backwards...
5009                                  */
5010                                 method_table_idx --;
5011                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5012                         }
5013                 } else {
5014                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5015                 }
5016                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5017         } else if (strcmp (klass->name, "MonoField") == 0) {
5018                 MonoReflectionField *f = (MonoReflectionField *)obj;
5019                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5020                         static guint32 field_table_idx = 0xffffff;
5021                         field_table_idx --;
5022                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5023                 } else {
5024                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5025                 }
5026                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5027         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5028                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5029                 token = mono_image_get_array_token (assembly, m);
5030         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5031                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5032                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5033         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5034                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5035                 token = mono_metadata_token_from_dor (
5036                         mono_image_typedef_or_ref (assembly, type));
5037         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5038                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5039                 token = mono_image_get_field_on_inst_token (assembly, f);
5040         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5041                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5042                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5043         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5044                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5045                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5046         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5047                 MonoReflectionType *type = (MonoReflectionType *)obj;
5048                 token = mono_metadata_token_from_dor (
5049                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5050         } else {
5051                 g_error ("requested token for %s\n", klass->name);
5052         }
5053
5054         if (register_token)
5055                 mono_image_register_token (assembly, token, obj);
5056
5057         return token;
5058 }
5059
5060 /*
5061  * mono_image_register_token:
5062  *
5063  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5064  * the Module.ResolveXXXToken () methods to work.
5065  */
5066 void
5067 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5068 {
5069         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5070         if (prev) {
5071                 /* There could be multiple MethodInfo objects with the same token */
5072                 //g_assert (prev == obj);
5073         } else {
5074                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5075         }
5076 }
5077
5078 static MonoDynamicImage*
5079 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5080 {
5081         static const guchar entrycode [16] = {0xff, 0x25, 0};
5082         MonoDynamicImage *image;
5083         int i;
5084
5085         const char *version;
5086
5087         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5088                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5089         else
5090                 version = mono_get_runtime_info ()->runtime_version;
5091
5092 #if HAVE_BOEHM_GC
5093         /* The MonoGHashTable's need GC tracking */
5094         image = GC_MALLOC (sizeof (MonoDynamicImage));
5095 #else
5096         image = g_new0 (MonoDynamicImage, 1);
5097 #endif
5098
5099         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5100         
5101         /*g_print ("created image %p\n", image);*/
5102         /* keep in sync with image.c */
5103         image->image.name = assembly_name;
5104         image->image.assembly_name = image->image.name; /* they may be different */
5105         image->image.module_name = module_name;
5106         image->image.version = g_strdup (version);
5107         image->image.md_version_major = 1;
5108         image->image.md_version_minor = 1;
5109         image->image.dynamic = TRUE;
5110
5111         image->image.references = g_new0 (MonoAssembly*, 1);
5112         image->image.references [0] = NULL;
5113
5114         mono_image_init (&image->image);
5115
5116         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5117         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5118         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5119         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5120         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5121         image->handleref = g_hash_table_new (NULL, NULL);
5122         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5123         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5124         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5125         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5126         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5127         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5128         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5129         image->gen_params = g_ptr_array_new ();
5130         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5131
5132         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5133         string_heap_init (&image->sheap);
5134         mono_image_add_stream_data (&image->us, "", 1);
5135         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5136         /* import tables... */
5137         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5138         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5139         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5140         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5141         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5142         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5143         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5144         stream_data_align (&image->code);
5145
5146         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5147
5148         for (i=0; i < MONO_TABLE_NUM; ++i) {
5149                 image->tables [i].next_idx = 1;
5150                 image->tables [i].columns = table_sizes [i];
5151         }
5152
5153         image->image.assembly = (MonoAssembly*)assembly;
5154         image->run = assembly->run;
5155         image->save = assembly->save;
5156         image->pe_kind = 0x1; /* ILOnly */
5157         image->machine = 0x14c; /* I386 */
5158         
5159         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5160
5161         return image;
5162 }
5163 #endif
5164
5165 static void
5166 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5167 {
5168         g_free (key);
5169 }
5170
5171 static void
5172 release_hashtable (MonoGHashTable **hash)
5173 {
5174         if (*hash) {
5175                 mono_g_hash_table_destroy (*hash);
5176                 *hash = NULL;
5177         }
5178 }
5179
5180 void
5181 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5182 {
5183         release_hashtable (&image->token_fixups);
5184         release_hashtable (&image->handleref_managed);
5185         release_hashtable (&image->tokens);
5186         release_hashtable (&image->remapped_tokens);
5187         release_hashtable (&image->generic_def_objects);
5188         release_hashtable (&image->methodspec);
5189 }
5190
5191 void
5192 mono_dynamic_image_free (MonoDynamicImage *image)
5193 {
5194         MonoDynamicImage *di = image;
5195         GList *list;
5196         int i;
5197
5198         if (di->methodspec)
5199                 mono_g_hash_table_destroy (di->methodspec);
5200         if (di->typespec)
5201                 g_hash_table_destroy (di->typespec);
5202         if (di->typeref)
5203                 g_hash_table_destroy (di->typeref);
5204         if (di->handleref)
5205                 g_hash_table_destroy (di->handleref);
5206         if (di->handleref_managed)
5207                 mono_g_hash_table_destroy (di->handleref_managed);
5208         if (di->tokens)
5209                 mono_g_hash_table_destroy (di->tokens);
5210         if (di->remapped_tokens)
5211                 mono_g_hash_table_destroy (di->remapped_tokens);
5212         if (di->generic_def_objects)
5213                 mono_g_hash_table_destroy (di->generic_def_objects);
5214         if (di->blob_cache) {
5215                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5216                 g_hash_table_destroy (di->blob_cache);
5217         }
5218         if (di->standalonesig_cache)
5219                 g_hash_table_destroy (di->standalonesig_cache);
5220         for (list = di->array_methods; list; list = list->next) {
5221                 ArrayMethod *am = (ArrayMethod *)list->data;
5222                 g_free (am->sig);
5223                 g_free (am->name);
5224                 g_free (am);
5225         }
5226         g_list_free (di->array_methods);
5227         if (di->gen_params) {
5228                 for (i = 0; i < di->gen_params->len; i++) {
5229                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5230                         mono_gc_deregister_root ((char*) &entry->gparam);
5231                         g_free (entry);
5232                 }
5233                 g_ptr_array_free (di->gen_params, TRUE);
5234         }
5235         if (di->token_fixups)
5236                 mono_g_hash_table_destroy (di->token_fixups);
5237         if (di->method_to_table_idx)
5238                 g_hash_table_destroy (di->method_to_table_idx);
5239         if (di->field_to_table_idx)
5240                 g_hash_table_destroy (di->field_to_table_idx);
5241         if (di->method_aux_hash)
5242                 g_hash_table_destroy (di->method_aux_hash);
5243         if (di->vararg_aux_hash)
5244                 g_hash_table_destroy (di->vararg_aux_hash);
5245         g_free (di->strong_name);
5246         g_free (di->win32_res);
5247         if (di->public_key)
5248                 g_free (di->public_key);
5249
5250         /*g_print ("string heap destroy for image %p\n", di);*/
5251         mono_dynamic_stream_reset (&di->sheap);
5252         mono_dynamic_stream_reset (&di->code);
5253         mono_dynamic_stream_reset (&di->resources);
5254         mono_dynamic_stream_reset (&di->us);
5255         mono_dynamic_stream_reset (&di->blob);
5256         mono_dynamic_stream_reset (&di->tstream);
5257         mono_dynamic_stream_reset (&di->guid);
5258         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5259                 g_free (di->tables [i].values);
5260         }
5261 }       
5262
5263 void
5264 mono_dynamic_image_free_image (MonoDynamicImage *image)
5265 {
5266         /* See create_dynamic_mono_image () */
5267 #if HAVE_BOEHM_GC
5268         /* Allocated using GC_MALLOC */
5269 #else
5270         g_free (image);
5271 #endif
5272 }
5273
5274 #ifndef DISABLE_REFLECTION_EMIT
5275
5276 /*
5277  * mono_image_basic_init:
5278  * @assembly: an assembly builder object
5279  *
5280  * Create the MonoImage that represents the assembly builder and setup some
5281  * of the helper hash table and the basic metadata streams.
5282  */
5283 void
5284 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5285 {
5286         MonoDynamicAssembly *assembly;
5287         MonoDynamicImage *image;
5288         MonoDomain *domain = mono_object_domain (assemblyb);
5289         
5290         MONO_ARCH_SAVE_REGS;
5291
5292         if (assemblyb->dynamic_assembly)
5293                 return;
5294
5295 #if HAVE_BOEHM_GC
5296         /* assembly->assembly.image might be GC allocated */
5297         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5298 #else
5299         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5300 #endif
5301
5302         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5303         
5304         assembly->assembly.ref_count = 1;
5305         assembly->assembly.dynamic = TRUE;
5306         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5307         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5308         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5309         if (assemblyb->culture)
5310                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5311         else
5312                 assembly->assembly.aname.culture = g_strdup ("");
5313
5314         if (assemblyb->version) {
5315                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5316                         char **version = g_strsplit (vstr, ".", 4);
5317                         char **parts = version;
5318                         assembly->assembly.aname.major = atoi (*parts++);
5319                         assembly->assembly.aname.minor = atoi (*parts++);
5320                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5321                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5322
5323                         g_strfreev (version);
5324                         g_free (vstr);
5325         } else {
5326                         assembly->assembly.aname.major = 0;
5327                         assembly->assembly.aname.minor = 0;
5328                         assembly->assembly.aname.build = 0;
5329                         assembly->assembly.aname.revision = 0;
5330         }
5331
5332         assembly->run = assemblyb->access != 2;
5333         assembly->save = assemblyb->access != 1;
5334         assembly->domain = domain;
5335
5336         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5337         image->initial_image = TRUE;
5338         assembly->assembly.aname.name = image->image.name;
5339         assembly->assembly.image = &image->image;
5340         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5341                 /* -1 to correct for the trailing NULL byte */
5342                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5343                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5344                 }
5345                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5346         }
5347
5348         mono_domain_assemblies_lock (domain);
5349         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5350         mono_domain_assemblies_unlock (domain);
5351
5352         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5353         
5354         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5355         
5356         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5357 }
5358
5359 #endif /* !DISABLE_REFLECTION_EMIT */
5360
5361 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5362
5363 static int
5364 calc_section_size (MonoDynamicImage *assembly)
5365 {
5366         int nsections = 0;
5367
5368         /* alignment constraints */
5369         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5370         g_assert ((assembly->code.index % 4) == 0);
5371         assembly->meta_size += 3;
5372         assembly->meta_size &= ~3;
5373         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5374         g_assert ((assembly->resources.index % 4) == 0);
5375
5376         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5377         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5378         nsections++;
5379
5380         if (assembly->win32_res) {
5381                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5382
5383                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5384                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5385                 nsections++;
5386         }
5387
5388         assembly->sections [MONO_SECTION_RELOC].size = 12;
5389         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5390         nsections++;
5391
5392         return nsections;
5393 }
5394
5395 typedef struct {
5396         guint32 id;
5397         guint32 offset;
5398         GSList *children;
5399         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5400 } ResTreeNode;
5401
5402 static int
5403 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5404 {
5405         ResTreeNode *t1 = (ResTreeNode*)a;
5406         ResTreeNode *t2 = (ResTreeNode*)b;
5407
5408         return t1->id - t2->id;
5409 }
5410
5411 /*
5412  * resource_tree_create:
5413  *
5414  *  Organize the resources into a resource tree.
5415  */
5416 static ResTreeNode *
5417 resource_tree_create (MonoArray *win32_resources)
5418 {
5419         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5420         GSList *l;
5421         int i;
5422
5423         tree = g_new0 (ResTreeNode, 1);
5424         
5425         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5426                 MonoReflectionWin32Resource *win32_res =
5427                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5428
5429                 /* Create node */
5430
5431                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5432                 lang_node = g_new0 (ResTreeNode, 1);
5433                 lang_node->id = win32_res->lang_id;
5434                 lang_node->win32_res = win32_res;
5435
5436                 /* Create type node if neccesary */
5437                 type_node = NULL;
5438                 for (l = tree->children; l; l = l->next)
5439                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5440                                 type_node = (ResTreeNode*)l->data;
5441                                 break;
5442                         }
5443
5444                 if (!type_node) {
5445                         type_node = g_new0 (ResTreeNode, 1);
5446                         type_node->id = win32_res->res_type;
5447
5448                         /* 
5449                          * The resource types have to be sorted otherwise
5450                          * Windows Explorer can't display the version information.
5451                          */
5452                         tree->children = g_slist_insert_sorted (tree->children, 
5453                                 type_node, resource_tree_compare_by_id);
5454                 }
5455
5456                 /* Create res node if neccesary */
5457                 res_node = NULL;
5458                 for (l = type_node->children; l; l = l->next)
5459                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5460                                 res_node = (ResTreeNode*)l->data;
5461                                 break;
5462                         }
5463
5464                 if (!res_node) {
5465                         res_node = g_new0 (ResTreeNode, 1);
5466                         res_node->id = win32_res->res_id;
5467                         type_node->children = g_slist_append (type_node->children, res_node);
5468                 }
5469
5470                 res_node->children = g_slist_append (res_node->children, lang_node);
5471         }
5472
5473         return tree;
5474 }
5475
5476 /*
5477  * resource_tree_encode:
5478  * 
5479  *   Encode the resource tree into the format used in the PE file.
5480  */
5481 static void
5482 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5483 {
5484         char *entries;
5485         MonoPEResourceDir dir;
5486         MonoPEResourceDirEntry dir_entry;
5487         MonoPEResourceDataEntry data_entry;
5488         GSList *l;
5489         guint32 res_id_entries;
5490
5491         /*
5492          * For the format of the resource directory, see the article
5493          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5494          * Matt Pietrek
5495          */
5496
5497         memset (&dir, 0, sizeof (dir));
5498         memset (&dir_entry, 0, sizeof (dir_entry));
5499         memset (&data_entry, 0, sizeof (data_entry));
5500
5501         g_assert (sizeof (dir) == 16);
5502         g_assert (sizeof (dir_entry) == 8);
5503         g_assert (sizeof (data_entry) == 16);
5504
5505         node->offset = p - begin;
5506
5507         /* IMAGE_RESOURCE_DIRECTORY */
5508         res_id_entries = g_slist_length (node->children);
5509         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5510
5511         memcpy (p, &dir, sizeof (dir));
5512         p += sizeof (dir);
5513
5514         /* Reserve space for entries */
5515         entries = p;
5516         p += sizeof (dir_entry) * res_id_entries;
5517
5518         /* Write children */
5519         for (l = node->children; l; l = l->next) {
5520                 ResTreeNode *child = (ResTreeNode*)l->data;
5521
5522                 if (child->win32_res) {
5523                         guint32 size;
5524
5525                         child->offset = p - begin;
5526
5527                         /* IMAGE_RESOURCE_DATA_ENTRY */
5528                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5529                         size = mono_array_length (child->win32_res->res_data);
5530                         data_entry.rde_size = GUINT32_TO_LE (size);
5531
5532                         memcpy (p, &data_entry, sizeof (data_entry));
5533                         p += sizeof (data_entry);
5534
5535                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5536                         p += size;
5537                 } else {
5538                         resource_tree_encode (child, begin, p, &p);
5539                 }
5540         }
5541
5542         /* IMAGE_RESOURCE_ENTRY */
5543         for (l = node->children; l; l = l->next) {
5544                 ResTreeNode *child = (ResTreeNode*)l->data;
5545
5546                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5547                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5548
5549                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5550                 entries += sizeof (dir_entry);
5551         }
5552
5553         *endbuf = p;
5554 }
5555
5556 static void
5557 resource_tree_free (ResTreeNode * node)
5558 {
5559         GSList * list;
5560         for (list = node->children; list; list = list->next)
5561                 resource_tree_free ((ResTreeNode*)list->data);
5562         g_slist_free(node->children);
5563         g_free (node);
5564 }
5565
5566 static void
5567 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5568 {
5569         char *buf;
5570         char *p;
5571         guint32 size, i;
5572         MonoReflectionWin32Resource *win32_res;
5573         ResTreeNode *tree;
5574
5575         if (!assemblyb->win32_resources)
5576                 return;
5577
5578         /*
5579          * Resources are stored in a three level tree inside the PE file.
5580          * - level one contains a node for each type of resource
5581          * - level two contains a node for each resource
5582          * - level three contains a node for each instance of a resource for a
5583          *   specific language.
5584          */
5585
5586         tree = resource_tree_create (assemblyb->win32_resources);
5587
5588         /* Estimate the size of the encoded tree */
5589         size = 0;
5590         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5591                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5592                 size += mono_array_length (win32_res->res_data);
5593         }
5594         /* Directory structure */
5595         size += mono_array_length (assemblyb->win32_resources) * 256;
5596         p = buf = g_malloc (size);
5597
5598         resource_tree_encode (tree, p, p, &p);
5599
5600         g_assert (p - buf <= size);
5601
5602         assembly->win32_res = g_malloc (p - buf);
5603         assembly->win32_res_size = p - buf;
5604         memcpy (assembly->win32_res, buf, p - buf);
5605
5606         g_free (buf);
5607         resource_tree_free (tree);
5608 }
5609
5610 static void
5611 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5612 {
5613         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5614         int i;
5615
5616         p += sizeof (MonoPEResourceDir);
5617         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5618                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5619                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5620                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5621                         fixup_resource_directory (res_section, child, rva);
5622                 } else {
5623                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5624                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5625                 }
5626
5627                 p += sizeof (MonoPEResourceDirEntry);
5628         }
5629 }
5630
5631 static void
5632 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5633 {
5634         guint32 dummy;
5635         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5636                 g_error ("WriteFile returned %d\n", GetLastError ());
5637 }
5638
5639 /*
5640  * mono_image_create_pefile:
5641  * @mb: a module builder object
5642  * 
5643  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5644  * assembly->pefile where it can be easily retrieved later in chunks.
5645  */
5646 void
5647 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5648 {
5649         MonoMSDOSHeader *msdos;
5650         MonoDotNetHeader *header;
5651         MonoSectionTable *section;
5652         MonoCLIHeader *cli_header;
5653         guint32 size, image_size, virtual_base, text_offset;
5654         guint32 header_start, section_start, file_offset, virtual_offset;
5655         MonoDynamicImage *assembly;
5656         MonoReflectionAssemblyBuilder *assemblyb;
5657         MonoDynamicStream pefile_stream = {0};
5658         MonoDynamicStream *pefile = &pefile_stream;
5659         int i, nsections;
5660         guint32 *rva, value;
5661         guchar *p;
5662         static const unsigned char msheader[] = {
5663                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5664                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5665                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5666                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5667                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5668                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5669                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5670                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5671         };
5672
5673         assemblyb = mb->assemblyb;
5674
5675         mono_image_basic_init (assemblyb);
5676         assembly = mb->dynamic_image;
5677
5678         assembly->pe_kind = assemblyb->pe_kind;
5679         assembly->machine = assemblyb->machine;
5680         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5681         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5682         
5683         mono_image_build_metadata (mb);
5684
5685         if (mb->is_main && assemblyb->resources) {
5686                 int len = mono_array_length (assemblyb->resources);
5687                 for (i = 0; i < len; ++i)
5688                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5689         }
5690
5691         if (mb->resources) {
5692                 int len = mono_array_length (mb->resources);
5693                 for (i = 0; i < len; ++i)
5694                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5695         }
5696
5697         build_compressed_metadata (assembly);
5698
5699         if (mb->is_main)
5700                 assembly_add_win32_resources (assembly, assemblyb);
5701
5702         nsections = calc_section_size (assembly);
5703         
5704         /* The DOS header and stub */
5705         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5706         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5707
5708         /* the dotnet header */
5709         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5710
5711         /* the section tables */
5712         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5713
5714         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5715         virtual_offset = VIRT_ALIGN;
5716         image_size = 0;
5717
5718         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5719                 if (!assembly->sections [i].size)
5720                         continue;
5721                 /* align offsets */
5722                 file_offset += FILE_ALIGN - 1;
5723                 file_offset &= ~(FILE_ALIGN - 1);
5724                 virtual_offset += VIRT_ALIGN - 1;
5725                 virtual_offset &= ~(VIRT_ALIGN - 1);
5726
5727                 assembly->sections [i].offset = file_offset;
5728                 assembly->sections [i].rva = virtual_offset;
5729
5730                 file_offset += assembly->sections [i].size;
5731                 virtual_offset += assembly->sections [i].size;
5732                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5733         }
5734
5735         file_offset += FILE_ALIGN - 1;
5736         file_offset &= ~(FILE_ALIGN - 1);
5737
5738         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5739
5740         /* back-patch info */
5741         msdos = (MonoMSDOSHeader*)pefile->data;
5742         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5743
5744         header = (MonoDotNetHeader*)(pefile->data + header_start);
5745         header->pesig [0] = 'P';
5746         header->pesig [1] = 'E';
5747         
5748         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5749         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5750         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5751         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5752         if (assemblyb->pekind == 1) {
5753                 /* it's a dll */
5754                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5755         } else {
5756                 /* it's an exe */
5757                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5758         }
5759
5760         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5761
5762         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5763         header->pe.pe_major = 6;
5764         header->pe.pe_minor = 0;
5765         size = assembly->sections [MONO_SECTION_TEXT].size;
5766         size += FILE_ALIGN - 1;
5767         size &= ~(FILE_ALIGN - 1);
5768         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5769         size = assembly->sections [MONO_SECTION_RSRC].size;
5770         size += FILE_ALIGN - 1;
5771         size &= ~(FILE_ALIGN - 1);
5772         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5773         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5774         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5775         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5776         /* pe_rva_entry_point always at the beginning of the text section */
5777         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5778
5779         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5780         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5781         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5782         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5783         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5784         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5785         size = section_start;
5786         size += FILE_ALIGN - 1;
5787         size &= ~(FILE_ALIGN - 1);
5788         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5789         size = image_size;
5790         size += VIRT_ALIGN - 1;
5791         size &= ~(VIRT_ALIGN - 1);
5792         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5793
5794         /*
5795         // Translate the PEFileKind value to the value expected by the Windows loader
5796         */
5797         {
5798                 short kind;
5799
5800                 /*
5801                 // PEFileKinds.Dll == 1
5802                 // PEFileKinds.ConsoleApplication == 2
5803                 // PEFileKinds.WindowApplication == 3
5804                 //
5805                 // need to get:
5806                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5807                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5808                 */
5809                 if (assemblyb->pekind == 3)
5810                         kind = 2;
5811                 else
5812                         kind = 3;
5813                 
5814                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5815         }    
5816         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5817         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5818         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5819         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5820         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5821         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5822
5823         /* fill data directory entries */
5824
5825         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5826         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5827
5828         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5829         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5830
5831         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5832         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5833         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5834         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5835         /* patch entrypoint name */
5836         if (assemblyb->pekind == 1)
5837                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5838         else
5839                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5840         /* patch imported function RVA name */
5841         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5842         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5843
5844         /* the import table */
5845         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5846         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5847         /* patch imported dll RVA name and other entries in the dir */
5848         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5849         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5850         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5851         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5852         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5853         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5854
5855         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5856         value = (assembly->text_rva + assembly->imp_names_offset);
5857         *p++ = (value) & 0xff;
5858         *p++ = (value >> 8) & (0xff);
5859         *p++ = (value >> 16) & (0xff);
5860         *p++ = (value >> 24) & (0xff);
5861
5862         /* the CLI header info */
5863         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5864         cli_header->ch_size = GUINT32_FROM_LE (72);
5865         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5866         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5867         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5868         if (assemblyb->entry_point) {
5869                 guint32 table_idx = 0;
5870                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5871                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5872                         table_idx = methodb->table_idx;
5873                 } else {
5874                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5875                 }
5876                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5877         } else {
5878                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5879         }
5880         /* The embedded managed resources */
5881         text_offset = assembly->text_rva + assembly->code.index;
5882         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5883         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5884         text_offset += assembly->resources.index;
5885         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5886         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5887         text_offset += assembly->meta_size;
5888         if (assembly->strong_name_size) {
5889                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5890                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5891                 text_offset += assembly->strong_name_size;
5892         }
5893
5894         /* write the section tables and section content */
5895         section = (MonoSectionTable*)(pefile->data + section_start);
5896         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5897                 static const char section_names [][7] = {
5898                         ".text", ".rsrc", ".reloc"
5899                 };
5900                 if (!assembly->sections [i].size)
5901                         continue;
5902                 strcpy (section->st_name, section_names [i]);
5903                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5904                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5905                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5906                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5907                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5908                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5909                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5910                 section ++;
5911         }
5912         
5913         checked_write_file (file, pefile->data, pefile->index);
5914         
5915         mono_dynamic_stream_reset (pefile);
5916         
5917         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5918                 if (!assembly->sections [i].size)
5919                         continue;
5920                 
5921                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5922                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5923                 
5924                 switch (i) {
5925                 case MONO_SECTION_TEXT:
5926                         /* patch entry point */
5927                         p = (guchar*)(assembly->code.data + 2);
5928                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5929                         *p++ = (value) & 0xff;
5930                         *p++ = (value >> 8) & 0xff;
5931                         *p++ = (value >> 16) & 0xff;
5932                         *p++ = (value >> 24) & 0xff;
5933                 
5934                         checked_write_file (file, assembly->code.data, assembly->code.index);
5935                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5936                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5937                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5938                                 
5939
5940                         g_free (assembly->image.raw_metadata);
5941                         break;
5942                 case MONO_SECTION_RELOC: {
5943                         struct {
5944                                 guint32 page_rva;
5945                                 guint32 block_size;
5946                                 guint16 type_and_offset;
5947                                 guint16 term;
5948                         } reloc;
5949                         
5950                         g_assert (sizeof (reloc) == 12);
5951                         
5952                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5953                         reloc.block_size = GUINT32_FROM_LE (12);
5954                         
5955                         /* 
5956                          * the entrypoint is always at the start of the text section 
5957                          * 3 is IMAGE_REL_BASED_HIGHLOW
5958                          * 2 is patch_size_rva - text_rva
5959                          */
5960                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5961                         reloc.term = 0;
5962                         
5963                         checked_write_file (file, &reloc, sizeof (reloc));
5964                         
5965                         break;
5966                 }
5967                 case MONO_SECTION_RSRC:
5968                         if (assembly->win32_res) {
5969
5970                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5971                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5972                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5973                         }
5974                         break;
5975                 default:
5976                         g_assert_not_reached ();
5977                 }
5978         }
5979         
5980         /* check that the file is properly padded */
5981         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5982                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5983         if (! SetEndOfFile (file))
5984                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5985         
5986         mono_dynamic_stream_reset (&assembly->code);
5987         mono_dynamic_stream_reset (&assembly->us);
5988         mono_dynamic_stream_reset (&assembly->blob);
5989         mono_dynamic_stream_reset (&assembly->guid);
5990         mono_dynamic_stream_reset (&assembly->sheap);
5991
5992         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5993         g_hash_table_destroy (assembly->blob_cache);
5994         assembly->blob_cache = NULL;
5995 }
5996
5997 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5998
5999 void
6000 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6001 {
6002         g_assert_not_reached ();
6003 }
6004
6005 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6006
6007 #ifndef DISABLE_REFLECTION_EMIT
6008
6009 MonoReflectionModule *
6010 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6011 {
6012         char *name;
6013         MonoImage *image;
6014         MonoImageOpenStatus status;
6015         MonoDynamicAssembly *assembly;
6016         guint32 module_count;
6017         MonoImage **new_modules;
6018         gboolean *new_modules_loaded;
6019         
6020         name = mono_string_to_utf8 (fileName);
6021
6022         image = mono_image_open (name, &status);
6023         if (!image) {
6024                 MonoException *exc;
6025                 if (status == MONO_IMAGE_ERROR_ERRNO)
6026                         exc = mono_get_exception_file_not_found (fileName);
6027                 else
6028                         exc = mono_get_exception_bad_image_format (name);
6029                 g_free (name);
6030                 mono_raise_exception (exc);
6031         }
6032
6033         g_free (name);
6034
6035         assembly = ab->dynamic_assembly;
6036         image->assembly = (MonoAssembly*)assembly;
6037
6038         module_count = image->assembly->image->module_count;
6039         new_modules = g_new0 (MonoImage *, module_count + 1);
6040         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6041
6042         if (image->assembly->image->modules)
6043                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6044         if (image->assembly->image->modules_loaded)
6045                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6046         new_modules [module_count] = image;
6047         new_modules_loaded [module_count] = TRUE;
6048         mono_image_addref (image);
6049
6050         g_free (image->assembly->image->modules);
6051         image->assembly->image->modules = new_modules;
6052         image->assembly->image->modules_loaded = new_modules_loaded;
6053         image->assembly->image->module_count ++;
6054
6055         mono_assembly_load_references (image, &status);
6056         if (status) {
6057                 mono_image_close (image);
6058                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6059         }
6060
6061         return mono_module_get_object (mono_domain_get (), image);
6062 }
6063
6064 #endif /* DISABLE_REFLECTION_EMIT */
6065
6066 /*
6067  * We need to return always the same object for MethodInfo, FieldInfo etc..
6068  * but we need to consider the reflected type.
6069  * type uses a different hash, since it uses custom hash/equal functions.
6070  */
6071
6072 typedef struct {
6073         gpointer item;
6074         MonoClass *refclass;
6075 } ReflectedEntry;
6076
6077 static gboolean
6078 reflected_equal (gconstpointer a, gconstpointer b) {
6079         const ReflectedEntry *ea = a;
6080         const ReflectedEntry *eb = b;
6081
6082         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6083 }
6084
6085 static guint
6086 reflected_hash (gconstpointer a) {
6087         const ReflectedEntry *ea = a;
6088         return mono_aligned_addr_hash (ea->item);
6089 }
6090
6091 #define CHECK_OBJECT(t,p,k)     \
6092         do {    \
6093                 t _obj; \
6094                 ReflectedEntry e;       \
6095                 e.item = (p);   \
6096                 e.refclass = (k);       \
6097                 mono_domain_lock (domain);      \
6098                 if (!domain->refobject_hash)    \
6099                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6100                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6101                         mono_domain_unlock (domain);    \
6102                         return _obj;    \
6103                 }       \
6104         mono_domain_unlock (domain); \
6105         } while (0)
6106
6107 #ifdef HAVE_BOEHM_GC
6108 /* ReflectedEntry doesn't need to be GC tracked */
6109 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6110 #define FREE_REFENTRY(entry) g_free ((entry))
6111 #define REFENTRY_REQUIRES_CLEANUP
6112 #else
6113 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6114 /* FIXME: */
6115 #define FREE_REFENTRY(entry)
6116 #endif
6117
6118 #define CACHE_OBJECT(t,p,o,k)   \
6119         do {    \
6120                 t _obj; \
6121         ReflectedEntry pe; \
6122         pe.item = (p); \
6123         pe.refclass = (k); \
6124         mono_domain_lock (domain); \
6125                 if (!domain->refobject_hash)    \
6126                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6127         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6128         if (!_obj) { \
6129                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6130                     e->item = (p);      \
6131                     e->refclass = (k);  \
6132                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6133             _obj = o; \
6134         } \
6135                 mono_domain_unlock (domain);    \
6136         return _obj; \
6137         } while (0)
6138
6139 static void
6140 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6141 {
6142         mono_domain_lock (domain);
6143         if (domain->refobject_hash) {
6144         ReflectedEntry pe;
6145                 gpointer orig_pe, orig_value;
6146
6147                 pe.item = o;
6148                 pe.refclass = klass;
6149                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6150                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6151                         FREE_REFENTRY (orig_pe);
6152                 }
6153         }
6154         mono_domain_unlock (domain);
6155 }
6156
6157 #ifdef REFENTRY_REQUIRES_CLEANUP
6158 static void
6159 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6160 {
6161         FREE_REFENTRY (key);
6162 }
6163 #endif
6164
6165 void
6166 mono_reflection_cleanup_domain (MonoDomain *domain)
6167 {
6168         if (domain->refobject_hash) {
6169 /*let's avoid scanning the whole hashtable if not needed*/
6170 #ifdef REFENTRY_REQUIRES_CLEANUP
6171                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6172 #endif
6173                 mono_g_hash_table_destroy (domain->refobject_hash);
6174                 domain->refobject_hash = NULL;
6175         }
6176 }
6177
6178 #ifndef DISABLE_REFLECTION_EMIT
6179 static gpointer
6180 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6181 {
6182         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6183 }
6184
6185 static gpointer
6186 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6187 {
6188         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6189 }
6190
6191 void
6192 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6193 {
6194         MonoDynamicImage *image = moduleb->dynamic_image;
6195         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6196         if (!image) {
6197                 MonoError error;
6198                 int module_count;
6199                 MonoImage **new_modules;
6200                 MonoImage *ass;
6201                 char *name, *fqname;
6202                 /*
6203                  * FIXME: we already created an image in mono_image_basic_init (), but
6204                  * we don't know which module it belongs to, since that is only 
6205                  * determined at assembly save time.
6206                  */
6207                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6208                 name = mono_string_to_utf8 (ab->name);
6209                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6210                 if (!mono_error_ok (&error)) {
6211                         g_free (name);
6212                         mono_error_raise_exception (&error);
6213                 }
6214                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6215
6216                 moduleb->module.image = &image->image;
6217                 moduleb->dynamic_image = image;
6218                 register_module (mono_object_domain (moduleb), moduleb, image);
6219
6220                 /* register the module with the assembly */
6221                 ass = ab->dynamic_assembly->assembly.image;
6222                 module_count = ass->module_count;
6223                 new_modules = g_new0 (MonoImage *, module_count + 1);
6224
6225                 if (ass->modules)
6226                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6227                 new_modules [module_count] = &image->image;
6228                 mono_image_addref (&image->image);
6229
6230                 g_free (ass->modules);
6231                 ass->modules = new_modules;
6232                 ass->module_count ++;
6233         }
6234 }
6235
6236 void
6237 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6238 {
6239         MonoDynamicImage *image = moduleb->dynamic_image;
6240
6241         g_assert (type->type);
6242         image->wrappers_type = mono_class_from_mono_type (type->type);
6243 }
6244
6245 #endif
6246
6247 /*
6248  * mono_assembly_get_object:
6249  * @domain: an app domain
6250  * @assembly: an assembly
6251  *
6252  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6253  */
6254 MonoReflectionAssembly*
6255 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6256 {
6257         static MonoClass *assembly_type;
6258         MonoReflectionAssembly *res;
6259         
6260         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6261         if (!assembly_type) {
6262                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6263                 if (class == NULL)
6264                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6265                 g_assert (class);
6266                 assembly_type = class;
6267         }
6268         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6269         res->assembly = assembly;
6270
6271         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6272 }
6273
6274
6275
6276 MonoReflectionModule*   
6277 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6278 {
6279         static MonoClass *module_type;
6280         MonoReflectionModule *res;
6281         char* basename;
6282         
6283         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6284         if (!module_type) {
6285                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6286                 if (class == NULL)
6287                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6288                 g_assert (class);
6289                 module_type = class;
6290         }
6291         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6292
6293         res->image = image;
6294         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6295
6296         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6297         basename = g_path_get_basename (image->name);
6298         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6299         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6300         
6301         g_free (basename);
6302
6303         if (image->assembly->image == image) {
6304                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6305         } else {
6306                 int i;
6307                 res->token = 0;
6308                 if (image->assembly->image->modules) {
6309                         for (i = 0; i < image->assembly->image->module_count; i++) {
6310                                 if (image->assembly->image->modules [i] == image)
6311                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6312                         }
6313                         g_assert (res->token);
6314                 }
6315         }
6316
6317         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6318 }
6319
6320 MonoReflectionModule*   
6321 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6322 {
6323         static MonoClass *module_type;
6324         MonoReflectionModule *res;
6325         MonoTableInfo *table;
6326         guint32 cols [MONO_FILE_SIZE];
6327         const char *name;
6328         guint32 i, name_idx;
6329         const char *val;
6330         
6331         if (!module_type) {
6332                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6333                 if (class == NULL)
6334                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6335                 g_assert (class);
6336                 module_type = class;
6337         }
6338         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6339
6340         table = &image->tables [MONO_TABLE_FILE];
6341         g_assert (table_index < table->rows);
6342         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6343
6344         res->image = NULL;
6345         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6346         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6347
6348         /* Check whenever the row has a corresponding row in the moduleref table */
6349         table = &image->tables [MONO_TABLE_MODULEREF];
6350         for (i = 0; i < table->rows; ++i) {
6351                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6352                 val = mono_metadata_string_heap (image, name_idx);
6353                 if (strcmp (val, name) == 0)
6354                         res->image = image->modules [i];
6355         }
6356
6357         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6358         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6359         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6360         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6361         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6362
6363         return res;
6364 }
6365
6366 static gboolean
6367 verify_safe_for_managed_space (MonoType *type)
6368 {
6369         switch (type->type) {
6370 #ifdef DEBUG_HARDER
6371         case MONO_TYPE_ARRAY:
6372                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6373         case MONO_TYPE_PTR:
6374                 return verify_safe_for_managed_space (type->data.type);
6375         case MONO_TYPE_SZARRAY:
6376                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6377         case MONO_TYPE_GENERICINST: {
6378                 MonoGenericInst *inst = type->data.generic_class->inst;
6379                 int i;
6380                 if (!inst->is_open)
6381                         break;
6382                 for (i = 0; i < inst->type_argc; ++i)
6383                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6384                                 return FALSE;
6385                 break;
6386         }
6387 #endif
6388         case MONO_TYPE_VAR:
6389         case MONO_TYPE_MVAR:
6390                 return TRUE;
6391         }
6392         return TRUE;
6393 }
6394
6395 static MonoType*
6396 mono_type_normalize (MonoType *type)
6397 {
6398         int i;
6399         MonoGenericClass *gclass;
6400         MonoGenericInst *ginst;
6401         MonoClass *gtd;
6402         MonoGenericContainer *gcontainer;
6403         MonoType **argv = NULL;
6404         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6405
6406         if (type->type != MONO_TYPE_GENERICINST)
6407                 return type;
6408
6409         gclass = type->data.generic_class;
6410         ginst = gclass->context.class_inst;
6411         if (!ginst->is_open)
6412                 return type;
6413
6414         gtd = gclass->container_class;
6415         gcontainer = gtd->generic_container;
6416         argv = g_newa (MonoType*, ginst->type_argc);
6417
6418         for (i = 0; i < ginst->type_argc; ++i) {
6419                 MonoType *t = ginst->type_argv [i], *norm;
6420                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6421                         is_denorm_gtd = FALSE;
6422                 norm = mono_type_normalize (t);
6423                 argv [i] = norm;
6424                 if (norm != t)
6425                         requires_rebind = TRUE;
6426         }
6427
6428         if (is_denorm_gtd)
6429                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6430
6431         if (requires_rebind) {
6432                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6433                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6434         }
6435
6436         return type;
6437 }
6438 /*
6439  * mono_type_get_object:
6440  * @domain: an app domain
6441  * @type: a type
6442  *
6443  * Return an System.MonoType object representing the type @type.
6444  */
6445 MonoReflectionType*
6446 mono_type_get_object (MonoDomain *domain, MonoType *type)
6447 {
6448         MonoType *norm_type;
6449         MonoReflectionType *res;
6450         MonoClass *klass = mono_class_from_mono_type (type);
6451
6452         /*we must avoid using @type as it might have come
6453          * from a mono_metadata_type_dup and the caller
6454          * expects that is can be freed.
6455          * Using the right type from 
6456          */
6457         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6458
6459         /* void is very common */
6460         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6461                 return (MonoReflectionType*)domain->typeof_void;
6462
6463         /*
6464          * If the vtable of the given class was already created, we can use
6465          * the MonoType from there and avoid all locking and hash table lookups.
6466          * 
6467          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6468          * that the resulting object is different.   
6469          */
6470         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6471                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6472                 if (vtable && vtable->type)
6473                         return vtable->type;
6474         }
6475
6476         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6477         mono_domain_lock (domain);
6478         if (!domain->type_hash)
6479                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6480                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6481         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6482                 mono_domain_unlock (domain);
6483                 mono_loader_unlock ();
6484                 return res;
6485         }
6486
6487         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6488          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6489          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6490          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6491          * artifact of how generics are encoded and should be transparent to managed code so we
6492          * need to weed out this diference when retrieving managed System.Type objects.
6493          */
6494         norm_type = mono_type_normalize (type);
6495         if (norm_type != type) {
6496                 res = mono_type_get_object (domain, norm_type);
6497                 mono_g_hash_table_insert (domain->type_hash, type, res);
6498                 mono_domain_unlock (domain);
6499                 mono_loader_unlock ();
6500                 return res;
6501         }
6502
6503         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6504         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6505                 g_assert (0);
6506
6507         if (!verify_safe_for_managed_space (type)) {
6508                 mono_domain_unlock (domain);
6509                 mono_loader_unlock ();
6510                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6511         }
6512
6513         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6514                 gboolean is_type_done = TRUE;
6515                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6516                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6517                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6518                 */
6519                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6520                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6521
6522                         if (gparam->owner && gparam->owner->is_method) {
6523                                 MonoMethod *method = gparam->owner->owner.method;
6524                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6525                                         is_type_done = FALSE;
6526                         } else if (gparam->owner && !gparam->owner->is_method) {
6527                                 MonoClass *klass = gparam->owner->owner.klass;
6528                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6529                                         is_type_done = FALSE;
6530                         }
6531                 } 
6532
6533                 /* g_assert_not_reached (); */
6534                 /* should this be considered an error condition? */
6535                 if (is_type_done && !type->byref) {
6536                         mono_domain_unlock (domain);
6537                         mono_loader_unlock ();
6538                         return mono_class_get_ref_info (klass);
6539                 }
6540         }
6541         /* This is stored in vtables/JITted code so it has to be pinned */
6542         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6543         res->type = type;
6544         mono_g_hash_table_insert (domain->type_hash, type, res);
6545
6546         if (type->type == MONO_TYPE_VOID)
6547                 domain->typeof_void = (MonoObject*)res;
6548
6549         mono_domain_unlock (domain);
6550         mono_loader_unlock ();
6551         return res;
6552 }
6553
6554 /*
6555  * mono_method_get_object:
6556  * @domain: an app domain
6557  * @method: a method
6558  * @refclass: the reflected type (can be NULL)
6559  *
6560  * Return an System.Reflection.MonoMethod object representing the method @method.
6561  */
6562 MonoReflectionMethod*
6563 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6564 {
6565         /*
6566          * We use the same C representation for methods and constructors, but the type 
6567          * name in C# is different.
6568          */
6569         static MonoClass *System_Reflection_MonoMethod = NULL;
6570         static MonoClass *System_Reflection_MonoCMethod = NULL;
6571         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6572         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6573         MonoClass *klass;
6574         MonoReflectionMethod *ret;
6575
6576         if (method->is_inflated) {
6577                 MonoReflectionGenericMethod *gret;
6578
6579                 refclass = method->klass;
6580                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6581                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6582                         if (!System_Reflection_MonoGenericCMethod)
6583                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6584                         klass = System_Reflection_MonoGenericCMethod;
6585                 } else {
6586                         if (!System_Reflection_MonoGenericMethod)
6587                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6588                         klass = System_Reflection_MonoGenericMethod;
6589                 }
6590                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6591                 gret->method.method = method;
6592                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6593                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6594                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6595         }
6596
6597         if (!refclass)
6598                 refclass = method->klass;
6599
6600         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6601         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6602                 if (!System_Reflection_MonoCMethod)
6603                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6604                 klass = System_Reflection_MonoCMethod;
6605         }
6606         else {
6607                 if (!System_Reflection_MonoMethod)
6608                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6609                 klass = System_Reflection_MonoMethod;
6610         }
6611         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6612         ret->method = method;
6613         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6614         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6615 }
6616
6617 /*
6618  * mono_method_clear_object:
6619  *
6620  *   Clear the cached reflection objects for the dynamic method METHOD.
6621  */
6622 void
6623 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6624 {
6625         MonoClass *klass;
6626         g_assert (method_is_dynamic (method));
6627
6628         klass = method->klass;
6629         while (klass) {
6630                 clear_cached_object (domain, method, klass);
6631                 klass = klass->parent;
6632         }
6633         /* Added by mono_param_get_objects () */
6634         clear_cached_object (domain, &(method->signature), NULL);
6635         klass = method->klass;
6636         while (klass) {
6637                 clear_cached_object (domain, &(method->signature), klass);
6638                 klass = klass->parent;
6639         }
6640 }
6641
6642 /*
6643  * mono_field_get_object:
6644  * @domain: an app domain
6645  * @klass: a type
6646  * @field: a field
6647  *
6648  * Return an System.Reflection.MonoField object representing the field @field
6649  * in class @klass.
6650  */
6651 MonoReflectionField*
6652 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6653 {
6654         MonoReflectionField *res;
6655         static MonoClass *monofield_klass;
6656
6657         CHECK_OBJECT (MonoReflectionField *, field, klass);
6658         if (!monofield_klass)
6659                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6660         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6661         res->klass = klass;
6662         res->field = field;
6663         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6664
6665         if (is_field_on_inst (field)) {
6666                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6667                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6668         } else {
6669                 if (field->type)
6670                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6671                 res->attrs = mono_field_get_flags (field);
6672         }
6673         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6674 }
6675
6676 /*
6677  * mono_property_get_object:
6678  * @domain: an app domain
6679  * @klass: a type
6680  * @property: a property
6681  *
6682  * Return an System.Reflection.MonoProperty object representing the property @property
6683  * in class @klass.
6684  */
6685 MonoReflectionProperty*
6686 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6687 {
6688         MonoReflectionProperty *res;
6689         static MonoClass *monoproperty_klass;
6690
6691         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6692         if (!monoproperty_klass)
6693                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6694         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6695         res->klass = klass;
6696         res->property = property;
6697         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6698 }
6699
6700 /*
6701  * mono_event_get_object:
6702  * @domain: an app domain
6703  * @klass: a type
6704  * @event: a event
6705  *
6706  * Return an System.Reflection.MonoEvent object representing the event @event
6707  * in class @klass.
6708  */
6709 MonoReflectionEvent*
6710 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6711 {
6712         MonoReflectionEvent *res;
6713         MonoReflectionMonoEvent *mono_event;
6714         static MonoClass *monoevent_klass;
6715
6716         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6717         if (!monoevent_klass)
6718                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6719         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6720         mono_event->klass = klass;
6721         mono_event->event = event;
6722         res = (MonoReflectionEvent*)mono_event;
6723         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6724 }
6725
6726 /**
6727  * mono_get_reflection_missing_object:
6728  * @domain: Domain where the object lives
6729  *
6730  * Returns the System.Reflection.Missing.Value singleton object
6731  * (of type System.Reflection.Missing).
6732  *
6733  * Used as the value for ParameterInfo.DefaultValue when Optional
6734  * is present
6735  */
6736 static MonoObject *
6737 mono_get_reflection_missing_object (MonoDomain *domain)
6738 {
6739         MonoObject *obj;
6740         static MonoClassField *missing_value_field = NULL;
6741         
6742         if (!missing_value_field) {
6743                 MonoClass *missing_klass;
6744                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6745                 mono_class_init (missing_klass);
6746                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6747                 g_assert (missing_value_field);
6748         }
6749         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6750         g_assert (obj);
6751         return obj;
6752 }
6753
6754 static MonoObject*
6755 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6756 {
6757         if (!*dbnull)
6758                 *dbnull = mono_get_dbnull_object (domain);
6759         return *dbnull;
6760 }
6761
6762 static MonoObject*
6763 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6764 {
6765         if (!*reflection_missing)
6766                 *reflection_missing = mono_get_reflection_missing_object (domain);
6767         return *reflection_missing;
6768 }
6769
6770 /*
6771  * mono_param_get_objects:
6772  * @domain: an app domain
6773  * @method: a method
6774  *
6775  * Return an System.Reflection.ParameterInfo array object representing the parameters
6776  * in the method @method.
6777  */
6778 MonoArray*
6779 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6780 {
6781         static MonoClass *System_Reflection_ParameterInfo;
6782         static MonoClass *System_Reflection_ParameterInfo_array;
6783         MonoError error;
6784         MonoArray *res = NULL;
6785         MonoReflectionMethod *member = NULL;
6786         MonoReflectionParameter *param = NULL;
6787         char **names, **blobs = NULL;
6788         guint32 *types = NULL;
6789         MonoType *type = NULL;
6790         MonoObject *dbnull = NULL;
6791         MonoObject *missing = NULL;
6792         MonoMarshalSpec **mspecs;
6793         MonoMethodSignature *sig;
6794         MonoVTable *pinfo_vtable;
6795         int i;
6796
6797         if (!System_Reflection_ParameterInfo_array) {
6798                 MonoClass *klass;
6799
6800                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6801                 if (!klass)
6802                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6803
6804                 mono_memory_barrier ();
6805                 System_Reflection_ParameterInfo = klass; 
6806
6807         
6808                 klass = mono_array_class_get (klass, 1);
6809                 mono_memory_barrier ();
6810                 System_Reflection_ParameterInfo_array = klass;
6811         }
6812
6813         sig = mono_method_signature_checked (method, &error);
6814         if (!mono_error_ok (&error))
6815                 mono_error_raise_exception (&error);
6816
6817         if (!sig->param_count)
6818                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6819
6820         /* Note: the cache is based on the address of the signature into the method
6821          * since we already cache MethodInfos with the method as keys.
6822          */
6823         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6824
6825         member = mono_method_get_object (domain, method, refclass);
6826         names = g_new (char *, sig->param_count);
6827         mono_method_get_param_names (method, (const char **) names);
6828
6829         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6830         mono_method_get_marshal_info (method, mspecs);
6831
6832         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6833         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6834         for (i = 0; i < sig->param_count; ++i) {
6835                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6836                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6837                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6838                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6839                 param->PositionImpl = i;
6840                 param->AttrsImpl = sig->params [i]->attrs;
6841
6842                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6843                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6844                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6845                         else
6846                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6847                 } else {
6848
6849                         if (!blobs) {
6850                                 blobs = g_new0 (char *, sig->param_count);
6851                                 types = g_new0 (guint32, sig->param_count);
6852                                 get_default_param_value_blobs (method, blobs, types); 
6853                         }
6854
6855                         /* Build MonoType for the type from the Constant Table */
6856                         if (!type)
6857                                 type = g_new0 (MonoType, 1);
6858                         type->type = types [i];
6859                         type->data.klass = NULL;
6860                         if (types [i] == MONO_TYPE_CLASS)
6861                                 type->data.klass = mono_defaults.object_class;
6862                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6863                                 /* For enums, types [i] contains the base type */
6864
6865                                         type->type = MONO_TYPE_VALUETYPE;
6866                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6867                         } else
6868                                 type->data.klass = mono_class_from_mono_type (type);
6869
6870                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6871
6872                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6873                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6874                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6875                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6876                                 else
6877                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6878                         }
6879                         
6880                 }
6881
6882                 if (mspecs [i + 1])
6883                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6884                 
6885                 mono_array_setref (res, i, param);
6886         }
6887         g_free (names);
6888         g_free (blobs);
6889         g_free (types);
6890         g_free (type);
6891
6892         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6893                 if (mspecs [i])
6894                         mono_metadata_free_marshal_spec (mspecs [i]);
6895         g_free (mspecs);
6896         
6897         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6898 }
6899
6900 MonoArray*
6901 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6902 {
6903         return mono_param_get_objects_internal (domain, method, NULL);
6904 }
6905
6906 /*
6907  * mono_method_body_get_object:
6908  * @domain: an app domain
6909  * @method: a method
6910  *
6911  * Return an System.Reflection.MethodBody object representing the method @method.
6912  */
6913 MonoReflectionMethodBody*
6914 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6915 {
6916         static MonoClass *System_Reflection_MethodBody = NULL;
6917         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6918         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6919         MonoReflectionMethodBody *ret;
6920         MonoMethodHeader *header;
6921         MonoImage *image;
6922         guint32 method_rva, local_var_sig_token;
6923     char *ptr;
6924         unsigned char format, flags;
6925         int i;
6926
6927         /* for compatibility with .net */
6928     if (method_is_dynamic (method))
6929         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6930
6931         if (!System_Reflection_MethodBody)
6932                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6933         if (!System_Reflection_LocalVariableInfo)
6934                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6935         if (!System_Reflection_ExceptionHandlingClause)
6936                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6937
6938         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6939
6940         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6941                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6942             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6943             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6944                 return NULL;
6945
6946         image = method->klass->image;
6947         header = mono_method_get_header (method);
6948
6949         if (!image_is_dynamic (image)) {
6950                 /* Obtain local vars signature token */
6951                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6952                 ptr = mono_image_rva_map (image, method_rva);
6953                 flags = *(const unsigned char *) ptr;
6954                 format = flags & METHOD_HEADER_FORMAT_MASK;
6955                 switch (format){
6956                 case METHOD_HEADER_TINY_FORMAT:
6957                         local_var_sig_token = 0;
6958                         break;
6959                 case METHOD_HEADER_FAT_FORMAT:
6960                         ptr += 2;
6961                         ptr += 2;
6962                         ptr += 4;
6963                         local_var_sig_token = read32 (ptr);
6964                         break;
6965                 default:
6966                         g_assert_not_reached ();
6967                 }
6968         } else
6969                 local_var_sig_token = 0; //FIXME
6970
6971         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6972
6973         ret->init_locals = header->init_locals;
6974         ret->max_stack = header->max_stack;
6975         ret->local_var_sig_token = local_var_sig_token;
6976         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6977         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6978
6979         /* Locals */
6980         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6981         for (i = 0; i < header->num_locals; ++i) {
6982                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6983                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6984                 info->is_pinned = header->locals [i]->pinned;
6985                 info->local_index = i;
6986                 mono_array_setref (ret->locals, i, info);
6987         }
6988
6989         /* Exceptions */
6990         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6991         for (i = 0; i < header->num_clauses; ++i) {
6992                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6993                 MonoExceptionClause *clause = &header->clauses [i];
6994
6995                 info->flags = clause->flags;
6996                 info->try_offset = clause->try_offset;
6997                 info->try_length = clause->try_len;
6998                 info->handler_offset = clause->handler_offset;
6999                 info->handler_length = clause->handler_len;
7000                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7001                         info->filter_offset = clause->data.filter_offset;
7002                 else if (clause->data.catch_class)
7003                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7004
7005                 mono_array_setref (ret->clauses, i, info);
7006         }
7007
7008         mono_metadata_free_mh (header);
7009         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7010         return ret;
7011 }
7012
7013 /**
7014  * mono_get_dbnull_object:
7015  * @domain: Domain where the object lives
7016  *
7017  * Returns the System.DBNull.Value singleton object
7018  *
7019  * Used as the value for ParameterInfo.DefaultValue 
7020  */
7021 MonoObject *
7022 mono_get_dbnull_object (MonoDomain *domain)
7023 {
7024         MonoObject *obj;
7025         static MonoClassField *dbnull_value_field = NULL;
7026         
7027         if (!dbnull_value_field) {
7028                 MonoClass *dbnull_klass;
7029                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7030                 mono_class_init (dbnull_klass);
7031                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7032                 g_assert (dbnull_value_field);
7033         }
7034         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7035         g_assert (obj);
7036         return obj;
7037 }
7038
7039 static void
7040 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7041 {
7042         guint32 param_index, i, lastp, crow = 0;
7043         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7044         gint32 idx;
7045
7046         MonoClass *klass = method->klass;
7047         MonoImage *image = klass->image;
7048         MonoMethodSignature *methodsig = mono_method_signature (method);
7049
7050         MonoTableInfo *constt;
7051         MonoTableInfo *methodt;
7052         MonoTableInfo *paramt;
7053
7054         if (!methodsig->param_count)
7055                 return;
7056
7057         mono_class_init (klass);
7058
7059         if (image_is_dynamic (klass->image)) {
7060                 MonoReflectionMethodAux *aux;
7061                 if (method->is_inflated)
7062                         method = ((MonoMethodInflated*)method)->declaring;
7063                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7064                 if (aux && aux->param_defaults) {
7065                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7066                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7067                 }
7068                 return;
7069         }
7070
7071         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7072         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7073         constt = &image->tables [MONO_TABLE_CONSTANT];
7074
7075         idx = mono_method_get_index (method) - 1;
7076         g_assert (idx != -1);
7077
7078         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7079         if (idx + 1 < methodt->rows)
7080                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7081         else
7082                 lastp = paramt->rows + 1;
7083
7084         for (i = param_index; i < lastp; ++i) {
7085                 guint32 paramseq;
7086
7087                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7088                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7089
7090                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7091                         continue;
7092
7093                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7094                 if (!crow) {
7095                         continue;
7096                 }
7097         
7098                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7099                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7100                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7101         }
7102
7103         return;
7104 }
7105
7106 MonoObject *
7107 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7108 {
7109         void *retval;
7110         MonoClass *klass;
7111         MonoObject *object;
7112         MonoType *basetype = type;
7113
7114         if (!blob)
7115                 return NULL;
7116         
7117         klass = mono_class_from_mono_type (type);
7118         if (klass->valuetype) {
7119                 object = mono_object_new (domain, klass);
7120                 retval = ((gchar *) object + sizeof (MonoObject));
7121                 if (klass->enumtype)
7122                         basetype = mono_class_enum_basetype (klass);
7123         } else {
7124                 retval = &object;
7125         }
7126                         
7127         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7128                 return object;
7129         else
7130                 return NULL;
7131 }
7132
7133 static int
7134 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7135         int found_sep;
7136         char *s;
7137         gboolean quoted = FALSE;
7138
7139         memset (assembly, 0, sizeof (MonoAssemblyName));
7140         assembly->culture = "";
7141         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7142
7143         if (*p == '"') {
7144                 quoted = TRUE;
7145                 p++;
7146         }
7147         assembly->name = p;
7148         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7149                 p++;
7150         if (quoted) {
7151                 if (*p != '"')
7152                         return 1;
7153                 *p = 0;
7154                 p++;
7155         }
7156         if (*p != ',')
7157                 return 1;
7158         *p = 0;
7159         /* Remove trailing whitespace */
7160         s = p - 1;
7161         while (*s && g_ascii_isspace (*s))
7162                 *s-- = 0;
7163         p ++;
7164         while (g_ascii_isspace (*p))
7165                 p++;
7166         while (*p) {
7167                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7168                         p += 8;
7169                         assembly->major = strtoul (p, &s, 10);
7170                         if (s == p || *s != '.')
7171                                 return 1;
7172                         p = ++s;
7173                         assembly->minor = strtoul (p, &s, 10);
7174                         if (s == p || *s != '.')
7175                                 return 1;
7176                         p = ++s;
7177                         assembly->build = strtoul (p, &s, 10);
7178                         if (s == p || *s != '.')
7179                                 return 1;
7180                         p = ++s;
7181                         assembly->revision = strtoul (p, &s, 10);
7182                         if (s == p)
7183                                 return 1;
7184                         p = s;
7185                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7186                         p += 8;
7187                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7188                                 assembly->culture = "";
7189                                 p += 7;
7190                         } else {
7191                                 assembly->culture = p;
7192                                 while (*p && *p != ',') {
7193                                         p++;
7194                                 }
7195                         }
7196                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7197                         p += 15;
7198                         if (strncmp (p, "null", 4) == 0) {
7199                                 p += 4;
7200                         } else {
7201                                 int len;
7202                                 gchar *start = p;
7203                                 while (*p && *p != ',') {
7204                                         p++;
7205                                 }
7206                                 len = (p - start + 1);
7207                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7208                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7209                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7210                         }
7211                 } else {
7212                         while (*p && *p != ',')
7213                                 p++;
7214                 }
7215                 found_sep = 0;
7216                 while (g_ascii_isspace (*p) || *p == ',') {
7217                         *p++ = 0;
7218                         found_sep = 1;
7219                         continue;
7220                 }
7221                 /* failed */
7222                 if (!found_sep)
7223                         return 1;
7224         }
7225
7226         return 0;
7227 }
7228
7229 /*
7230  * mono_reflection_parse_type:
7231  * @name: type name
7232  *
7233  * Parse a type name as accepted by the GetType () method and output the info
7234  * extracted in the info structure.
7235  * the name param will be mangled, so, make a copy before passing it to this function.
7236  * The fields in info will be valid until the memory pointed to by name is valid.
7237  *
7238  * See also mono_type_get_name () below.
7239  *
7240  * Returns: 0 on parse error.
7241  */
7242 static int
7243 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7244                              MonoTypeNameParse *info)
7245 {
7246         char *start, *p, *w, *last_point, *startn;
7247         int in_modifiers = 0;
7248         int isbyref = 0, rank = 0;
7249
7250         start = p = w = name;
7251
7252         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7253         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7254         info->name = info->name_space = NULL;
7255         info->nested = NULL;
7256         info->modifiers = NULL;
7257         info->type_arguments = NULL;
7258
7259         /* last_point separates the namespace from the name */
7260         last_point = NULL;
7261         /* Skips spaces */
7262         while (*p == ' ') p++, start++, w++, name++;
7263
7264         while (*p) {
7265                 switch (*p) {
7266                 case '+':
7267                         *p = 0; /* NULL terminate the name */
7268                         startn = p + 1;
7269                         info->nested = g_list_append (info->nested, startn);
7270                         /* we have parsed the nesting namespace + name */
7271                         if (info->name)
7272                                 break;
7273                         if (last_point) {
7274                                 info->name_space = start;
7275                                 *last_point = 0;
7276                                 info->name = last_point + 1;
7277                         } else {
7278                                 info->name_space = (char *)"";
7279                                 info->name = start;
7280                         }
7281                         break;
7282                 case '.':
7283                         last_point = p;
7284                         break;
7285                 case '\\':
7286                         ++p;
7287                         break;
7288                 case '&':
7289                 case '*':
7290                 case '[':
7291                 case ',':
7292                 case ']':
7293                         in_modifiers = 1;
7294                         break;
7295                 default:
7296                         break;
7297                 }
7298                 if (in_modifiers)
7299                         break;
7300                 // *w++ = *p++;
7301                 p++;
7302         }
7303         
7304         if (!info->name) {
7305                 if (last_point) {
7306                         info->name_space = start;
7307                         *last_point = 0;
7308                         info->name = last_point + 1;
7309                 } else {
7310                         info->name_space = (char *)"";
7311                         info->name = start;
7312                 }
7313         }
7314         while (*p) {
7315                 switch (*p) {
7316                 case '&':
7317                         if (isbyref) /* only one level allowed by the spec */
7318                                 return 0;
7319                         isbyref = 1;
7320                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7321                         *p++ = 0;
7322                         break;
7323                 case '*':
7324                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7325                         *p++ = 0;
7326                         break;
7327                 case '[':
7328                         //Decide if it's an array of a generic argument list
7329                         *p++ = 0;
7330
7331                         if (!*p) //XXX test
7332                                 return 0;
7333                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7334                                 rank = 1;
7335                                 while (*p) {
7336                                         if (*p == ']')
7337                                                 break;
7338                                         if (*p == ',')
7339                                                 rank++;
7340                                         else if (*p == '*') /* '*' means unknown lower bound */
7341                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7342                                         else
7343                                                 return 0;
7344                                         ++p;
7345                                 }
7346                                 if (*p++ != ']')
7347                                         return 0;
7348                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7349                         } else {
7350                                 if (rank) /* generic args after array spec*/ //XXX test
7351                                         return 0;
7352                                 info->type_arguments = g_ptr_array_new ();
7353                                 while (*p) {
7354                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7355                                         gboolean fqname = FALSE;
7356
7357                                         g_ptr_array_add (info->type_arguments, subinfo);
7358
7359                                         if (*p == '[') {
7360                                                 p++;
7361                                                 fqname = TRUE;
7362                                         }
7363
7364                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7365                                                 return 0;
7366
7367                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7368                                         if (fqname && (*p != ']')) {
7369                                                 char *aname;
7370
7371                                                 if (*p != ',')
7372                                                         return 0;
7373                                                 *p++ = 0;
7374
7375                                                 aname = p;
7376                                                 while (*p && (*p != ']'))
7377                                                         p++;
7378
7379                                                 if (*p != ']')
7380                                                         return 0;
7381
7382                                                 *p++ = 0;
7383                                                 while (*aname) {
7384                                                         if (g_ascii_isspace (*aname)) {
7385                                                                 ++aname;
7386                                                                 continue;
7387                                                         }
7388                                                         break;
7389                                                 }
7390                                                 if (!*aname ||
7391                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7392                                                         return 0;
7393                                         } else if (fqname && (*p == ']')) {
7394                                                 *p++ = 0;
7395                                         }
7396                                         if (*p == ']') {
7397                                                 *p++ = 0;
7398                                                 break;
7399                                         } else if (!*p) {
7400                                                 return 0;
7401                                         }
7402                                         *p++ = 0;
7403                                 }
7404                         }
7405                         break;
7406                 case ']':
7407                         if (is_recursed)
7408                                 goto end;
7409                         return 0;
7410                 case ',':
7411                         if (is_recursed)
7412                                 goto end;
7413                         *p++ = 0;
7414                         while (*p) {
7415                                 if (g_ascii_isspace (*p)) {
7416                                         ++p;
7417                                         continue;
7418                                 }
7419                                 break;
7420                         }
7421                         if (!*p)
7422                                 return 0; /* missing assembly name */
7423                         if (!assembly_name_to_aname (&info->assembly, p))
7424                                 return 0;
7425                         break;
7426                 default:
7427                         return 0;
7428                 }
7429                 if (info->assembly.name)
7430                         break;
7431         }
7432         // *w = 0; /* terminate class name */
7433  end:
7434         if (!info->name || !*info->name)
7435                 return 0;
7436         if (endptr)
7437                 *endptr = p;
7438         /* add other consistency checks */
7439         return 1;
7440 }
7441
7442 int
7443 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7444 {
7445         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7446 }
7447
7448 static MonoType*
7449 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7450 {
7451         gboolean type_resolve = FALSE;
7452         MonoType *type;
7453         MonoImage *rootimage = image;
7454
7455         if (info->assembly.name) {
7456                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7457                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7458                         /* 
7459                          * This could happen in the AOT compiler case when the search hook is not
7460                          * installed.
7461                          */
7462                         assembly = image->assembly;
7463                 if (!assembly) {
7464                         /* then we must load the assembly ourselve - see #60439 */
7465                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7466                         if (!assembly)
7467                                 return NULL;
7468                 }
7469                 image = assembly->image;
7470         } else if (!image) {
7471                 image = mono_defaults.corlib;
7472         }
7473
7474         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7475         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7476                 image = mono_defaults.corlib;
7477                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7478         }
7479
7480         return type;
7481 }
7482
7483 static MonoType*
7484 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7485 {
7486         MonoClass *klass;
7487         GList *mod;
7488         int modval;
7489         gboolean bounded = FALSE;
7490         
7491         if (!image)
7492                 image = mono_defaults.corlib;
7493
7494         if (ignorecase) {
7495                 MonoError error;
7496                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7497                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7498         } else {
7499                 klass = mono_class_from_name (image, info->name_space, info->name);
7500         }
7501         if (!klass)
7502                 return NULL;
7503         for (mod = info->nested; mod; mod = mod->next) {
7504                 gpointer iter = NULL;
7505                 MonoClass *parent;
7506
7507                 parent = klass;
7508                 mono_class_init (parent);
7509
7510                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7511                         char *lastp;
7512                         char *nested_name, *nested_nspace;
7513                         gboolean match = TRUE;
7514
7515                         lastp = strrchr (mod->data, '.');
7516                         if (lastp) {
7517                                 /* Nested classes can have namespaces */
7518                                 int nspace_len;
7519
7520                                 nested_name = g_strdup (lastp + 1);
7521                                 nspace_len = lastp - (char*)mod->data;
7522                                 nested_nspace = g_malloc (nspace_len + 1);
7523                                 memcpy (nested_nspace, mod->data, nspace_len);
7524                                 nested_nspace [nspace_len] = '\0';
7525
7526                         } else {
7527                                 nested_name = mod->data;
7528                                 nested_nspace = NULL;
7529                         }
7530
7531                         if (nested_nspace) {
7532                                 if (ignorecase) {
7533                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7534                                                 match = FALSE;
7535                                 } else {
7536                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7537                                                 match = FALSE;
7538                                 }
7539                         }
7540                         if (match) {
7541                                 if (ignorecase) {
7542                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7543                                                 match = FALSE;
7544                                 } else {
7545                                         if (strcmp (klass->name, nested_name) != 0)
7546                                                 match = FALSE;
7547                                 }
7548                         }
7549                         if (lastp) {
7550                                 g_free (nested_name);
7551                                 g_free (nested_nspace);
7552                         }
7553                         if (match)
7554                                 break;
7555                 }
7556
7557                 if (!klass)
7558                         break;
7559         }
7560         if (!klass)
7561                 return NULL;
7562
7563         if (info->type_arguments) {
7564                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7565                 MonoReflectionType *the_type;
7566                 MonoType *instance;
7567                 int i;
7568
7569                 for (i = 0; i < info->type_arguments->len; i++) {
7570                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7571
7572                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7573                         if (!type_args [i]) {
7574                                 g_free (type_args);
7575                                 return NULL;
7576                         }
7577                 }
7578
7579                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7580
7581                 instance = mono_reflection_bind_generic_parameters (
7582                         the_type, info->type_arguments->len, type_args);
7583
7584                 g_free (type_args);
7585                 if (!instance)
7586                         return NULL;
7587
7588                 klass = mono_class_from_mono_type (instance);
7589         }
7590
7591         for (mod = info->modifiers; mod; mod = mod->next) {
7592                 modval = GPOINTER_TO_UINT (mod->data);
7593                 if (!modval) { /* byref: must be last modifier */
7594                         return &klass->this_arg;
7595                 } else if (modval == -1) {
7596                         klass = mono_ptr_class_get (&klass->byval_arg);
7597                 } else if (modval == -2) {
7598                         bounded = TRUE;
7599                 } else { /* array rank */
7600                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7601                 }
7602         }
7603
7604         return &klass->byval_arg;
7605 }
7606
7607 /*
7608  * mono_reflection_get_type:
7609  * @image: a metadata context
7610  * @info: type description structure
7611  * @ignorecase: flag for case-insensitive string compares
7612  * @type_resolve: whenever type resolve was already tried
7613  *
7614  * Build a MonoType from the type description in @info.
7615  * 
7616  */
7617
7618 MonoType*
7619 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7620         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7621 }
7622
7623 static MonoType*
7624 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7625 {
7626         MonoReflectionAssemblyBuilder *abuilder;
7627         MonoType *type;
7628         int i;
7629
7630         g_assert (assembly_is_dynamic (assembly));
7631         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7632
7633         /* Enumerate all modules */
7634
7635         type = NULL;
7636         if (abuilder->modules) {
7637                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7638                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7639                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7640                         if (type)
7641                                 break;
7642                 }
7643         }
7644
7645         if (!type && abuilder->loaded_modules) {
7646                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7647                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7648                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7649                         if (type)
7650                                 break;
7651                 }
7652         }
7653
7654         return type;
7655 }
7656         
7657 MonoType*
7658 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7659 {
7660         MonoType *type;
7661         MonoReflectionAssembly *assembly;
7662         GString *fullName;
7663         GList *mod;
7664
7665         if (image && image_is_dynamic (image))
7666                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7667         else
7668                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7669         if (type)
7670                 return type;
7671         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7672                 return NULL;
7673
7674         if (type_resolve) {
7675                 if (*type_resolve) 
7676                         return NULL;
7677                 else
7678                         *type_resolve = TRUE;
7679         }
7680         
7681         /* Reconstruct the type name */
7682         fullName = g_string_new ("");
7683         if (info->name_space && (info->name_space [0] != '\0'))
7684                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7685         else
7686                 g_string_printf (fullName, "%s", info->name);
7687         for (mod = info->nested; mod; mod = mod->next)
7688                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7689
7690         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7691         if (assembly) {
7692                 if (assembly_is_dynamic (assembly->assembly))
7693                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7694                 else
7695                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7696                                                                                                           info, ignorecase);
7697         }
7698         g_string_free (fullName, TRUE);
7699         return type;
7700 }
7701
7702 void
7703 mono_reflection_free_type_info (MonoTypeNameParse *info)
7704 {
7705         g_list_free (info->modifiers);
7706         g_list_free (info->nested);
7707
7708         if (info->type_arguments) {
7709                 int i;
7710
7711                 for (i = 0; i < info->type_arguments->len; i++) {
7712                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7713
7714                         mono_reflection_free_type_info (subinfo);
7715                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7716                         g_free (subinfo);
7717                 }
7718
7719                 g_ptr_array_free (info->type_arguments, TRUE);
7720         }
7721 }
7722
7723 /*
7724  * mono_reflection_type_from_name:
7725  * @name: type name.
7726  * @image: a metadata context (can be NULL).
7727  *
7728  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7729  * it defaults to get the type from @image or, if @image is NULL or loading
7730  * from it fails, uses corlib.
7731  * 
7732  */
7733 MonoType*
7734 mono_reflection_type_from_name (char *name, MonoImage *image)
7735 {
7736         MonoType *type = NULL;
7737         MonoTypeNameParse info;
7738         char *tmp;
7739
7740         /* Make a copy since parse_type modifies its argument */
7741         tmp = g_strdup (name);
7742         
7743         /*g_print ("requested type %s\n", str);*/
7744         if (mono_reflection_parse_type (tmp, &info)) {
7745                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7746         }
7747
7748         g_free (tmp);
7749         mono_reflection_free_type_info (&info);
7750         return type;
7751 }
7752
7753 /*
7754  * mono_reflection_get_token:
7755  *
7756  *   Return the metadata token of OBJ which should be an object
7757  * representing a metadata element.
7758  */
7759 guint32
7760 mono_reflection_get_token (MonoObject *obj)
7761 {
7762         MonoClass *klass;
7763         guint32 token = 0;
7764
7765         klass = obj->vtable->klass;
7766
7767         if (strcmp (klass->name, "MethodBuilder") == 0) {
7768                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7769
7770                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7771         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7772                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7773
7774                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7775         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7776                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7777
7778                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7779         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7780                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7781                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7782         } else if (strcmp (klass->name, "MonoType") == 0) {
7783                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7784                 MonoClass *mc = mono_class_from_mono_type (type);
7785                 if (!mono_class_init (mc))
7786                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7787
7788                 token = mc->type_token;
7789         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7790                    strcmp (klass->name, "MonoMethod") == 0 ||
7791                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7792                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7793                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7794                 if (m->method->is_inflated) {
7795                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7796                         return inflated->declaring->token;
7797                 } else {
7798                         token = m->method->token;
7799                 }
7800         } else if (strcmp (klass->name, "MonoField") == 0) {
7801                 MonoReflectionField *f = (MonoReflectionField*)obj;
7802
7803                 if (is_field_on_inst (f->field)) {
7804                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7805                         int field_index = f->field - dgclass->fields;
7806                         MonoObject *obj;
7807
7808                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7809                         obj = dgclass->field_objects [field_index];
7810                         return mono_reflection_get_token (obj);
7811                 }
7812                 token = mono_class_get_field_token (f->field);
7813         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7814                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7815
7816                 token = mono_class_get_property_token (p->property);
7817         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7818                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7819
7820                 token = mono_class_get_event_token (p->event);
7821         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
7822                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7823                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7824                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7825
7826                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7827         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7828                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7829
7830                 token = m->token;
7831         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7832                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7833         } else {
7834                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7835                 MonoException *ex = mono_get_exception_not_implemented (msg);
7836                 g_free (msg);
7837                 mono_raise_exception (ex);
7838         }
7839
7840         return token;
7841 }
7842
7843 static MonoClass*
7844 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
7845 {
7846         char *n;
7847         MonoType *t;
7848         int slen = mono_metadata_decode_value (p, &p);
7849
7850         mono_error_init (error);
7851
7852         n = g_memdup (p, slen + 1);
7853         n [slen] = 0;
7854         t = mono_reflection_type_from_name (n, image);
7855         if (!t) {
7856                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7857                 /* We don't free n, it's consumed by mono_error */
7858                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
7859                 return NULL;
7860         }
7861         g_free (n);
7862         p += slen;
7863         *end = p;
7864         return mono_class_from_mono_type (t);
7865 }
7866
7867 static void*
7868 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
7869 {
7870         int slen, type = t->type;
7871         MonoClass *tklass = t->data.klass;
7872
7873         mono_error_init (error);
7874
7875 handle_enum:
7876         switch (type) {
7877         case MONO_TYPE_U1:
7878         case MONO_TYPE_I1:
7879         case MONO_TYPE_BOOLEAN: {
7880                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7881                 *bval = *p;
7882                 *end = p + 1;
7883                 return bval;
7884         }
7885         case MONO_TYPE_CHAR:
7886         case MONO_TYPE_U2:
7887         case MONO_TYPE_I2: {
7888                 guint16 *val = g_malloc (sizeof (guint16));
7889                 *val = read16 (p);
7890                 *end = p + 2;
7891                 return val;
7892         }
7893 #if SIZEOF_VOID_P == 4
7894         case MONO_TYPE_U:
7895         case MONO_TYPE_I:
7896 #endif
7897         case MONO_TYPE_R4:
7898         case MONO_TYPE_U4:
7899         case MONO_TYPE_I4: {
7900                 guint32 *val = g_malloc (sizeof (guint32));
7901                 *val = read32 (p);
7902                 *end = p + 4;
7903                 return val;
7904         }
7905 #if SIZEOF_VOID_P == 8
7906         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7907         case MONO_TYPE_I:
7908 #endif
7909         case MONO_TYPE_U8:
7910         case MONO_TYPE_I8: {
7911                 guint64 *val = g_malloc (sizeof (guint64));
7912                 *val = read64 (p);
7913                 *end = p + 8;
7914                 return val;
7915         }
7916         case MONO_TYPE_R8: {
7917                 double *val = g_malloc (sizeof (double));
7918                 readr8 (p, val);
7919                 *end = p + 8;
7920                 return val;
7921         }
7922         case MONO_TYPE_VALUETYPE:
7923                 if (t->data.klass->enumtype) {
7924                         type = mono_class_enum_basetype (t->data.klass)->type;
7925                         goto handle_enum;
7926                 } else {
7927                         MonoClass *k =  t->data.klass;
7928                         
7929                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7930                                 guint64 *val = g_malloc (sizeof (guint64));
7931                                 *val = read64 (p);
7932                                 *end = p + 8;
7933                                 return val;
7934                         }
7935                 }
7936                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7937                 break;
7938                 
7939         case MONO_TYPE_STRING:
7940                 if (*p == (char)0xFF) {
7941                         *end = p + 1;
7942                         return NULL;
7943                 }
7944                 slen = mono_metadata_decode_value (p, &p);
7945                 *end = p + slen;
7946                 return mono_string_new_len (mono_domain_get (), p, slen);
7947         case MONO_TYPE_CLASS: {
7948                 char *n;
7949                 MonoType *t;
7950                 if (*p == (char)0xFF) {
7951                         *end = p + 1;
7952                         return NULL;
7953                 }
7954 handle_type:
7955                 slen = mono_metadata_decode_value (p, &p);
7956                 n = g_memdup (p, slen + 1);
7957                 n [slen] = 0;
7958                 t = mono_reflection_type_from_name (n, image);
7959                 if (!t) {
7960                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
7961                         /* We don't free n, it's consumed by mono_error */
7962                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
7963                         return NULL;
7964                 }
7965                 g_free (n);
7966                 *end = p + slen;
7967                 return mono_type_get_object (mono_domain_get (), t);
7968         }
7969         case MONO_TYPE_OBJECT: {
7970                 char subt = *p++;
7971                 MonoObject *obj;
7972                 MonoClass *subc = NULL;
7973                 void *val;
7974
7975                 if (subt == 0x50) {
7976                         goto handle_type;
7977                 } else if (subt == 0x0E) {
7978                         type = MONO_TYPE_STRING;
7979                         goto handle_enum;
7980                 } else if (subt == 0x1D) {
7981                         MonoType simple_type = {{0}};
7982                         int etype = *p;
7983                         p ++;
7984
7985                         type = MONO_TYPE_SZARRAY;
7986                         if (etype == 0x50) {
7987                                 tklass = mono_defaults.systemtype_class;
7988                         } else if (etype == 0x55) {
7989                                 tklass = load_cattr_enum_type (image, p, &p, error);
7990                                 if (!mono_error_ok (error))
7991                                         return NULL;
7992                         } else {
7993                                 if (etype == 0x51)
7994                                         /* See Partition II, Appendix B3 */
7995                                         etype = MONO_TYPE_OBJECT;
7996                                 simple_type.type = etype;
7997                                 tklass = mono_class_from_mono_type (&simple_type);
7998                         }
7999                         goto handle_enum;
8000                 } else if (subt == 0x55) {
8001                         char *n;
8002                         MonoType *t;
8003                         slen = mono_metadata_decode_value (p, &p);
8004                         n = g_memdup (p, slen + 1);
8005                         n [slen] = 0;
8006                         t = mono_reflection_type_from_name (n, image);
8007                         if (!t) {
8008                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8009                                 /* We don't free n, it's consumed by mono_error */
8010                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8011                                 return NULL;
8012                         }
8013                         g_free (n);
8014                         p += slen;
8015                         subc = mono_class_from_mono_type (t);
8016                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8017                         MonoType simple_type = {{0}};
8018                         simple_type.type = subt;
8019                         subc = mono_class_from_mono_type (&simple_type);
8020                 } else {
8021                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8022                 }
8023                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8024                 obj = NULL;
8025                 if (mono_error_ok (error)) {
8026                         obj = mono_object_new (mono_domain_get (), subc);
8027                         g_assert (!subc->has_references);
8028                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8029                 }
8030
8031                 g_free (val);
8032                 return obj;
8033         }
8034         case MONO_TYPE_SZARRAY: {
8035                 MonoArray *arr;
8036                 guint32 i, alen, basetype;
8037                 alen = read32 (p);
8038                 p += 4;
8039                 if (alen == 0xffffffff) {
8040                         *end = p;
8041                         return NULL;
8042                 }
8043                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8044                 basetype = tklass->byval_arg.type;
8045                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8046                         basetype = mono_class_enum_basetype (tklass)->type;
8047                 switch (basetype)
8048                 {
8049                         case MONO_TYPE_U1:
8050                         case MONO_TYPE_I1:
8051                         case MONO_TYPE_BOOLEAN:
8052                                 for (i = 0; i < alen; i++) {
8053                                         MonoBoolean val = *p++;
8054                                         mono_array_set (arr, MonoBoolean, i, val);
8055                                 }
8056                                 break;
8057                         case MONO_TYPE_CHAR:
8058                         case MONO_TYPE_U2:
8059                         case MONO_TYPE_I2:
8060                                 for (i = 0; i < alen; i++) {
8061                                         guint16 val = read16 (p);
8062                                         mono_array_set (arr, guint16, i, val);
8063                                         p += 2;
8064                                 }
8065                                 break;
8066                         case MONO_TYPE_R4:
8067                         case MONO_TYPE_U4:
8068                         case MONO_TYPE_I4:
8069                                 for (i = 0; i < alen; i++) {
8070                                         guint32 val = read32 (p);
8071                                         mono_array_set (arr, guint32, i, val);
8072                                         p += 4;
8073                                 }
8074                                 break;
8075                         case MONO_TYPE_R8:
8076                                 for (i = 0; i < alen; i++) {
8077                                         double val;
8078                                         readr8 (p, &val);
8079                                         mono_array_set (arr, double, i, val);
8080                                         p += 8;
8081                                 }
8082                                 break;
8083                         case MONO_TYPE_U8:
8084                         case MONO_TYPE_I8:
8085                                 for (i = 0; i < alen; i++) {
8086                                         guint64 val = read64 (p);
8087                                         mono_array_set (arr, guint64, i, val);
8088                                         p += 8;
8089                                 }
8090                                 break;
8091                         case MONO_TYPE_CLASS:
8092                         case MONO_TYPE_OBJECT:
8093                         case MONO_TYPE_STRING:
8094                         case MONO_TYPE_SZARRAY:
8095                                 for (i = 0; i < alen; i++) {
8096                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8097                                         if (!mono_error_ok (error))
8098                                                 return NULL;
8099                                         mono_array_setref (arr, i, item);
8100                                 }
8101                                 break;
8102                         default:
8103                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8104                 }
8105                 *end=p;
8106                 return arr;
8107         }
8108         default:
8109                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8110         }
8111         return NULL;
8112 }
8113
8114 static MonoObject*
8115 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8116 {
8117         static MonoClass *klass;
8118         static MonoMethod *ctor;
8119         MonoObject *retval;
8120         void *params [2], *unboxed;
8121
8122         if (!klass)
8123                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8124         if (!ctor)
8125                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8126         
8127         params [0] = mono_type_get_object (mono_domain_get (), t);
8128         params [1] = val;
8129         retval = mono_object_new (mono_domain_get (), klass);
8130         unboxed = mono_object_unbox (retval);
8131         mono_runtime_invoke (ctor, unboxed, params, NULL);
8132
8133         return retval;
8134 }
8135
8136 static MonoObject*
8137 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8138 {
8139         static MonoClass *klass;
8140         static MonoMethod *ctor;
8141         MonoObject *retval;
8142         void *unboxed, *params [2];
8143
8144         if (!klass)
8145                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8146         if (!ctor)
8147                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8148
8149         params [0] = minfo;
8150         params [1] = typedarg;
8151         retval = mono_object_new (mono_domain_get (), klass);
8152         unboxed = mono_object_unbox (retval);
8153         mono_runtime_invoke (ctor, unboxed, params, NULL);
8154
8155         return retval;
8156 }
8157
8158 static gboolean
8159 type_is_reference (MonoType *type)
8160 {
8161         switch (type->type) {
8162         case MONO_TYPE_BOOLEAN:
8163         case MONO_TYPE_CHAR:
8164         case MONO_TYPE_U:
8165         case MONO_TYPE_I:
8166         case MONO_TYPE_U1:
8167         case MONO_TYPE_I1:
8168         case MONO_TYPE_U2:
8169         case MONO_TYPE_I2:
8170         case MONO_TYPE_U4:
8171         case MONO_TYPE_I4:
8172         case MONO_TYPE_U8:
8173         case MONO_TYPE_I8:
8174         case MONO_TYPE_R8:
8175         case MONO_TYPE_R4:
8176         case MONO_TYPE_VALUETYPE:
8177                 return FALSE;
8178         default:
8179                 return TRUE;
8180         }
8181 }
8182
8183 static void
8184 free_param_data (MonoMethodSignature *sig, void **params) {
8185         int i;
8186         for (i = 0; i < sig->param_count; ++i) {
8187                 if (!type_is_reference (sig->params [i]))
8188                         g_free (params [i]);
8189         }
8190 }
8191
8192 /*
8193  * Find the field index in the metadata FieldDef table.
8194  */
8195 static guint32
8196 find_field_index (MonoClass *klass, MonoClassField *field) {
8197         int i;
8198
8199         for (i = 0; i < klass->field.count; ++i) {
8200                 if (field == &klass->fields [i])
8201                         return klass->field.first + 1 + i;
8202         }
8203         return 0;
8204 }
8205
8206 /*
8207  * Find the property index in the metadata Property table.
8208  */
8209 static guint32
8210 find_property_index (MonoClass *klass, MonoProperty *property) {
8211         int i;
8212
8213         for (i = 0; i < klass->ext->property.count; ++i) {
8214                 if (property == &klass->ext->properties [i])
8215                         return klass->ext->property.first + 1 + i;
8216         }
8217         return 0;
8218 }
8219
8220 /*
8221  * Find the event index in the metadata Event table.
8222  */
8223 static guint32
8224 find_event_index (MonoClass *klass, MonoEvent *event) {
8225         int i;
8226
8227         for (i = 0; i < klass->ext->event.count; ++i) {
8228                 if (event == &klass->ext->events [i])
8229                         return klass->ext->event.first + 1 + i;
8230         }
8231         return 0;
8232 }
8233
8234 static MonoObject*
8235 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8236 {
8237         const char *p = (const char*)data;
8238         const char *named;
8239         guint32 i, j, num_named;
8240         MonoObject *attr;
8241         void *params_buf [32];
8242         void **params = NULL;
8243         MonoMethodSignature *sig;
8244         MonoObject *exc = NULL;
8245
8246         mono_error_init (error);
8247
8248         mono_class_init (method->klass);
8249
8250         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8251                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8252                 return NULL;
8253         }
8254
8255         if (len == 0) {
8256                 attr = mono_object_new (mono_domain_get (), method->klass);
8257                 mono_runtime_invoke (method, attr, NULL, NULL);
8258                 return attr;
8259         }
8260
8261         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8262                 return NULL;
8263
8264         /*g_print ("got attr %s\n", method->klass->name);*/
8265
8266         sig = mono_method_signature (method);
8267         if (sig->param_count < 32) {
8268                 params = params_buf;
8269                 memset (params, 0, sizeof (void*) * sig->param_count);
8270         } else {
8271                 /* Allocate using GC so it gets GC tracking */
8272                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8273         }
8274
8275         /* skip prolog */
8276         p += 2;
8277         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8278                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8279                 if (!mono_error_ok (error))
8280                         goto fail;
8281         }
8282
8283         named = p;
8284         attr = mono_object_new (mono_domain_get (), method->klass);
8285
8286         mono_runtime_invoke (method, attr, params, &exc);
8287         if (exc)
8288                 goto fail;
8289         num_named = read16 (named);
8290         named += 2;
8291         for (j = 0; j < num_named; j++) {
8292                 gint name_len;
8293                 char *name, named_type, data_type;
8294                 named_type = *named++;
8295                 data_type = *named++; /* type of data */
8296                 if (data_type == MONO_TYPE_SZARRAY)
8297                         data_type = *named++;
8298                 if (data_type == MONO_TYPE_ENUM) {
8299                         gint type_len;
8300                         char *type_name;
8301                         type_len = mono_metadata_decode_blob_size (named, &named);
8302                         type_name = g_malloc (type_len + 1);
8303                         memcpy (type_name, named, type_len);
8304                         type_name [type_len] = 0;
8305                         named += type_len;
8306                         /* FIXME: lookup the type and check type consistency */
8307                         g_free (type_name);
8308                 }
8309                 name_len = mono_metadata_decode_blob_size (named, &named);
8310                 name = g_malloc (name_len + 1);
8311                 memcpy (name, named, name_len);
8312                 name [name_len] = 0;
8313                 named += name_len;
8314                 if (named_type == 0x53) {
8315                         MonoClassField *field;
8316                         void *val;
8317
8318                         /* how this fail is a blackbox */
8319                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8320                         if (!field) {
8321                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8322                                 g_free (name);
8323                                 goto fail;
8324                         }
8325
8326                         val = load_cattr_value (image, field->type, named, &named, error);
8327                         if (!mono_error_ok (error)) {
8328                                 g_free (name);
8329                                 if (!type_is_reference (field->type))
8330                                         g_free (val);
8331                                 goto fail;
8332                         }
8333
8334                         mono_field_set_value (attr, field, val);
8335                         if (!type_is_reference (field->type))
8336                                 g_free (val);
8337                 } else if (named_type == 0x54) {
8338                         MonoProperty *prop;
8339                         void *pparams [1];
8340                         MonoType *prop_type;
8341
8342                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8343
8344                         if (!prop) {
8345                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8346                                 g_free (name);
8347                                 goto fail;
8348                         }
8349
8350                         if (!prop->set) {
8351                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8352                                 g_free (name);
8353                                 goto fail;
8354                         }
8355
8356                         /* can we have more that 1 arg in a custom attr named property? */
8357                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8358                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8359
8360                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8361                         if (!mono_error_ok (error)) {
8362                                 g_free (name);
8363                                 if (!type_is_reference (prop_type))
8364                                         g_free (pparams [0]);
8365                                 goto fail;
8366                         }
8367
8368
8369                         mono_property_set_value (prop, attr, pparams, NULL);
8370                         if (!type_is_reference (prop_type))
8371                                 g_free (pparams [0]);
8372                 }
8373                 g_free (name);
8374         }
8375
8376         free_param_data (method->signature, params);
8377         if (params != params_buf)
8378                 mono_gc_free_fixed (params);
8379
8380         return attr;
8381
8382 fail:
8383         free_param_data (method->signature, params);
8384         if (params != params_buf)
8385                 mono_gc_free_fixed (params);
8386         if (exc)
8387                 mono_raise_exception ((MonoException*)exc);
8388         return NULL;
8389 }
8390         
8391 /*
8392  * mono_reflection_create_custom_attr_data_args:
8393  *
8394  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8395  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8396  * NAMED_ARG_INFO will contain information about the named arguments.
8397  */
8398 void
8399 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
8400 {
8401         MonoArray *typedargs, *namedargs;
8402         MonoClass *attrklass;
8403         MonoDomain *domain;
8404         const char *p = (const char*)data;
8405         const char *named;
8406         guint32 i, j, num_named;
8407         CattrNamedArg *arginfo = NULL;
8408
8409         *typed_args = NULL;
8410         *named_args = NULL;
8411         *named_arg_info = NULL;
8412
8413         mono_error_init (error);
8414
8415         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8416                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8417                 return;
8418         }
8419
8420         mono_class_init (method->klass);
8421         
8422         domain = mono_domain_get ();
8423
8424         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8425                 return;
8426
8427         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8428         
8429         /* skip prolog */
8430         p += 2;
8431         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8432                 MonoObject *obj;
8433                 void *val;
8434
8435                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8436                 if (!mono_error_ok (error)) {
8437                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8438                                 g_free (val);
8439                         return;
8440                 }
8441
8442                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8443                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8444                 mono_array_setref (typedargs, i, obj);
8445
8446                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8447                         g_free (val);
8448         }
8449
8450         named = p;
8451         num_named = read16 (named);
8452         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8453         named += 2;
8454         attrklass = method->klass;
8455
8456         arginfo = g_new0 (CattrNamedArg, num_named);
8457         *named_arg_info = arginfo;
8458
8459         for (j = 0; j < num_named; j++) {
8460                 gint name_len;
8461                 char *name, named_type, data_type;
8462                 named_type = *named++;
8463                 data_type = *named++; /* type of data */
8464                 if (data_type == MONO_TYPE_SZARRAY)
8465                         data_type = *named++;
8466                 if (data_type == MONO_TYPE_ENUM) {
8467                         gint type_len;
8468                         char *type_name;
8469                         type_len = mono_metadata_decode_blob_size (named, &named);
8470                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8471                                 goto fail;
8472
8473                         type_name = g_malloc (type_len + 1);
8474                         memcpy (type_name, named, type_len);
8475                         type_name [type_len] = 0;
8476                         named += type_len;
8477                         /* FIXME: lookup the type and check type consistency */
8478                         g_free (type_name);
8479                 }
8480                 name_len = mono_metadata_decode_blob_size (named, &named);
8481                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8482                         goto fail;
8483                 name = g_malloc (name_len + 1);
8484                 memcpy (name, named, name_len);
8485                 name [name_len] = 0;
8486                 named += name_len;
8487                 if (named_type == 0x53) {
8488                         MonoObject *obj;
8489                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8490                         void *val;
8491
8492                         if (!field) {
8493                                 g_free (name);
8494                                 goto fail;
8495                         }
8496
8497                         arginfo [j].type = field->type;
8498                         arginfo [j].field = field;
8499
8500                         val = load_cattr_value (image, field->type, named, &named, error);
8501                         if (!mono_error_ok (error)) {
8502                                 if (!type_is_reference (field->type))
8503                                         g_free (val);
8504                                 g_free (name);
8505                                 return;
8506                         }
8507
8508                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8509                         mono_array_setref (namedargs, j, obj);
8510                         if (!type_is_reference (field->type))
8511                                 g_free (val);
8512                 } else if (named_type == 0x54) {
8513                         MonoObject *obj;
8514                         MonoType *prop_type;
8515                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8516                         void *val;
8517
8518                         if (!prop || !prop->set) {
8519                                 g_free (name);
8520                                 goto fail;
8521                         }
8522
8523                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8524                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8525
8526                         arginfo [j].type = prop_type;
8527                         arginfo [j].prop = prop;
8528
8529                         val = load_cattr_value (image, prop_type, named, &named, error);
8530                         if (!mono_error_ok (error)) {
8531                                 if (!type_is_reference (prop_type))
8532                                         g_free (val);
8533                                 g_free (name);
8534                                 return;
8535                         }
8536
8537                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8538                         mono_array_setref (namedargs, j, obj);
8539                         if (!type_is_reference (prop_type))
8540                                 g_free (val);
8541                 }
8542                 g_free (name);
8543         }
8544
8545         *typed_args = typedargs;
8546         *named_args = namedargs;
8547         return;
8548 fail:
8549         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8550         g_free (arginfo);
8551         *named_arg_info = NULL;
8552 }
8553
8554 void
8555 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8556 {
8557         MonoDomain *domain;
8558         MonoArray *typedargs, *namedargs;
8559         MonoImage *image;
8560         MonoMethod *method;
8561         CattrNamedArg *arginfo = NULL;
8562         MonoError error;
8563         int i;
8564
8565         *ctor_args = NULL;
8566         *named_args = NULL;
8567
8568         if (len == 0)
8569                 return;
8570
8571         image = assembly->assembly->image;
8572         method = ref_method->method;
8573         domain = mono_object_domain (ref_method);
8574
8575         if (!mono_class_init (method->klass))
8576                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8577
8578         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8579         if (!mono_error_ok (&error))
8580                 mono_error_raise_exception (&error);
8581         if (mono_loader_get_last_error ())
8582                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8583
8584         if (!typedargs || !namedargs) {
8585                 g_free (arginfo);
8586                 return;
8587         }
8588
8589         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8590                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8591                 MonoObject *typedarg;
8592
8593                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8594                 mono_array_setref (typedargs, i, typedarg);
8595         }
8596
8597         for (i = 0; i < mono_array_length (namedargs); ++i) {
8598                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8599                 MonoObject *typedarg, *namedarg, *minfo;
8600
8601                 if (arginfo [i].prop)
8602                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8603                 else
8604                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8605
8606                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8607                 namedarg = create_cattr_named_arg (minfo, typedarg);
8608
8609                 mono_array_setref (namedargs, i, namedarg);
8610         }
8611
8612         *ctor_args = typedargs;
8613         *named_args = namedargs;
8614         g_free (arginfo);
8615 }
8616
8617 static MonoObject*
8618 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8619 {
8620         static MonoMethod *ctor;
8621         MonoDomain *domain;
8622         MonoObject *attr;
8623         void *params [4];
8624
8625         g_assert (image->assembly);
8626
8627         if (!ctor)
8628                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8629
8630         domain = mono_domain_get ();
8631         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8632         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8633         params [1] = mono_assembly_get_object (domain, image->assembly);
8634         params [2] = (gpointer)&cattr->data;
8635         params [3] = &cattr->data_size;
8636         mono_runtime_invoke (ctor, attr, params, NULL);
8637         return attr;
8638 }
8639
8640 static MonoArray*
8641 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8642 {
8643         MonoArray *result;
8644         MonoObject *attr;
8645         int i, n;
8646
8647         mono_error_init (error);
8648
8649         n = 0;
8650         for (i = 0; i < cinfo->num_attrs; ++i) {
8651                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8652                         n ++;
8653         }
8654
8655         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8656         n = 0;
8657         for (i = 0; i < cinfo->num_attrs; ++i) {
8658                 if (!cinfo->attrs [i].ctor)
8659                         /* The cattr type is not finished yet */
8660                         /* We should include the type name but cinfo doesn't contain it */
8661                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8662                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8663                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8664                         if (!mono_error_ok (error))
8665                                 return result;
8666                         mono_array_setref (result, n, attr);
8667                         n ++;
8668                 }
8669         }
8670         return result;
8671 }
8672
8673 MonoArray*
8674 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8675 {
8676         MonoError error;
8677         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8678         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8679
8680         return result;
8681 }
8682
8683 static MonoArray*
8684 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8685 {
8686         MonoArray *result;
8687         MonoObject *attr;
8688         int i;
8689         
8690         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8691         for (i = 0; i < cinfo->num_attrs; ++i) {
8692                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8693                 mono_array_setref (result, i, attr);
8694         }
8695         return result;
8696 }
8697
8698 /**
8699  * mono_custom_attrs_from_index:
8700  *
8701  * Returns: NULL if no attributes are found or if a loading error occurs.
8702  */
8703 MonoCustomAttrInfo*
8704 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8705 {
8706         guint32 mtoken, i, len;
8707         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8708         MonoTableInfo *ca;
8709         MonoCustomAttrInfo *ainfo;
8710         GList *tmp, *list = NULL;
8711         const char *data;
8712
8713         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8714
8715         i = mono_metadata_custom_attrs_from_index (image, idx);
8716         if (!i)
8717                 return NULL;
8718         i --;
8719         while (i < ca->rows) {
8720                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8721                         break;
8722                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8723                 ++i;
8724         }
8725         len = g_list_length (list);
8726         if (!len)
8727                 return NULL;
8728         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8729         ainfo->num_attrs = len;
8730         ainfo->image = image;
8731         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8732                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8733                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8734                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8735                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8736                         mtoken |= MONO_TOKEN_METHOD_DEF;
8737                         break;
8738                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8739                         mtoken |= MONO_TOKEN_MEMBER_REF;
8740                         break;
8741                 default:
8742                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8743                         break;
8744                 }
8745                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8746                 if (!ainfo->attrs [i].ctor) {
8747                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8748                         g_list_free (list);
8749                         g_free (ainfo);
8750                         return NULL;
8751                 }
8752
8753                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8754                         /*FIXME raising an exception here doesn't make any sense*/
8755                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8756                         g_list_free (list);
8757                         g_free (ainfo);
8758                         return NULL;
8759                 }
8760                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8761                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8762                 ainfo->attrs [i].data = (guchar*)data;
8763         }
8764         g_list_free (list);
8765
8766         return ainfo;
8767 }
8768
8769 MonoCustomAttrInfo*
8770 mono_custom_attrs_from_method (MonoMethod *method)
8771 {
8772         guint32 idx;
8773
8774         /*
8775          * An instantiated method has the same cattrs as the generic method definition.
8776          *
8777          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8778          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8779          */
8780         if (method->is_inflated)
8781                 method = ((MonoMethodInflated *) method)->declaring;
8782         
8783         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8784                 return lookup_custom_attr (method->klass->image, method);
8785
8786         if (!method->token)
8787                 /* Synthetic methods */
8788                 return NULL;
8789
8790         idx = mono_method_get_index (method);
8791         idx <<= MONO_CUSTOM_ATTR_BITS;
8792         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8793         return mono_custom_attrs_from_index (method->klass->image, idx);
8794 }
8795
8796 MonoCustomAttrInfo*
8797 mono_custom_attrs_from_class (MonoClass *klass)
8798 {
8799         guint32 idx;
8800
8801         if (klass->generic_class)
8802                 klass = klass->generic_class->container_class;
8803
8804         if (image_is_dynamic (klass->image))
8805                 return lookup_custom_attr (klass->image, klass);
8806
8807         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8808                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8809                 idx <<= MONO_CUSTOM_ATTR_BITS;
8810                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8811         } else {
8812                 idx = mono_metadata_token_index (klass->type_token);
8813                 idx <<= MONO_CUSTOM_ATTR_BITS;
8814                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8815         }
8816         return mono_custom_attrs_from_index (klass->image, idx);
8817 }
8818
8819 MonoCustomAttrInfo*
8820 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8821 {
8822         guint32 idx;
8823         
8824         if (image_is_dynamic (assembly->image))
8825                 return lookup_custom_attr (assembly->image, assembly);
8826         idx = 1; /* there is only one assembly */
8827         idx <<= MONO_CUSTOM_ATTR_BITS;
8828         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8829         return mono_custom_attrs_from_index (assembly->image, idx);
8830 }
8831
8832 static MonoCustomAttrInfo*
8833 mono_custom_attrs_from_module (MonoImage *image)
8834 {
8835         guint32 idx;
8836         
8837         if (image_is_dynamic (image))
8838                 return lookup_custom_attr (image, image);
8839         idx = 1; /* there is only one module */
8840         idx <<= MONO_CUSTOM_ATTR_BITS;
8841         idx |= MONO_CUSTOM_ATTR_MODULE;
8842         return mono_custom_attrs_from_index (image, idx);
8843 }
8844
8845 MonoCustomAttrInfo*
8846 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8847 {
8848         guint32 idx;
8849         
8850         if (image_is_dynamic (klass->image)) {
8851                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8852                 return lookup_custom_attr (klass->image, property);
8853         }
8854         idx = find_property_index (klass, property);
8855         idx <<= MONO_CUSTOM_ATTR_BITS;
8856         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8857         return mono_custom_attrs_from_index (klass->image, idx);
8858 }
8859
8860 MonoCustomAttrInfo*
8861 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8862 {
8863         guint32 idx;
8864         
8865         if (image_is_dynamic (klass->image)) {
8866                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8867                 return lookup_custom_attr (klass->image, event);
8868         }
8869         idx = find_event_index (klass, event);
8870         idx <<= MONO_CUSTOM_ATTR_BITS;
8871         idx |= MONO_CUSTOM_ATTR_EVENT;
8872         return mono_custom_attrs_from_index (klass->image, idx);
8873 }
8874
8875 MonoCustomAttrInfo*
8876 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8877 {
8878         guint32 idx;
8879         if (image_is_dynamic (klass->image)) {
8880                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8881                 return lookup_custom_attr (klass->image, field);
8882         }
8883         idx = find_field_index (klass, field);
8884         idx <<= MONO_CUSTOM_ATTR_BITS;
8885         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8886         return mono_custom_attrs_from_index (klass->image, idx);
8887 }
8888
8889 /**
8890  * mono_custom_attrs_from_param:
8891  * @method: handle to the method that we want to retrieve custom parameter information from
8892  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
8893  *
8894  * The result must be released with mono_custom_attrs_free().
8895  *
8896  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
8897  */
8898 MonoCustomAttrInfo*
8899 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8900 {
8901         MonoTableInfo *ca;
8902         guint32 i, idx, method_index;
8903         guint32 param_list, param_last, param_pos, found;
8904         MonoImage *image;
8905         MonoReflectionMethodAux *aux;
8906
8907         /*
8908          * An instantiated method has the same cattrs as the generic method definition.
8909          *
8910          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8911          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8912          */
8913         if (method->is_inflated)
8914                 method = ((MonoMethodInflated *) method)->declaring;
8915
8916         if (image_is_dynamic (method->klass->image)) {
8917                 MonoCustomAttrInfo *res, *ainfo;
8918                 int size;
8919
8920                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8921                 if (!aux || !aux->param_cattr)
8922                         return NULL;
8923
8924                 /* Need to copy since it will be freed later */
8925                 ainfo = aux->param_cattr [param];
8926                 if (!ainfo)
8927                         return NULL;
8928                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8929                 res = g_malloc0 (size);
8930                 memcpy (res, ainfo, size);
8931                 return res;
8932         }
8933
8934         image = method->klass->image;
8935         method_index = mono_method_get_index (method);
8936         if (!method_index)
8937                 return NULL;
8938         ca = &image->tables [MONO_TABLE_METHOD];
8939
8940         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8941         if (method_index == ca->rows) {
8942                 ca = &image->tables [MONO_TABLE_PARAM];
8943                 param_last = ca->rows + 1;
8944         } else {
8945                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8946                 ca = &image->tables [MONO_TABLE_PARAM];
8947         }
8948         found = FALSE;
8949         for (i = param_list; i < param_last; ++i) {
8950                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8951                 if (param_pos == param) {
8952                         found = TRUE;
8953                         break;
8954                 }
8955         }
8956         if (!found)
8957                 return NULL;
8958         idx = i;
8959         idx <<= MONO_CUSTOM_ATTR_BITS;
8960         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8961         return mono_custom_attrs_from_index (image, idx);
8962 }
8963
8964 gboolean
8965 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8966 {
8967         int i;
8968         MonoClass *klass;
8969         for (i = 0; i < ainfo->num_attrs; ++i) {
8970                 klass = ainfo->attrs [i].ctor->klass;
8971                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8972                         return TRUE;
8973         }
8974         return FALSE;
8975 }
8976
8977 MonoObject*
8978 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8979 {
8980         MonoError error;
8981         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
8982         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8983         return res;
8984 }
8985
8986 MonoObject*
8987 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
8988 {
8989         int i, attr_index;
8990         MonoClass *klass;
8991         MonoArray *attrs;
8992
8993         mono_error_init (error);
8994
8995         attr_index = -1;
8996         for (i = 0; i < ainfo->num_attrs; ++i) {
8997                 klass = ainfo->attrs [i].ctor->klass;
8998                 if (mono_class_has_parent (klass, attr_klass)) {
8999                         attr_index = i;
9000                         break;
9001                 }
9002         }
9003         if (attr_index == -1)
9004                 return NULL;
9005
9006         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9007         if (!mono_error_ok (error))
9008                 return NULL;
9009         return mono_array_get (attrs, MonoObject*, attr_index);
9010 }
9011
9012 /*
9013  * mono_reflection_get_custom_attrs_info:
9014  * @obj: a reflection object handle
9015  *
9016  * Return the custom attribute info for attributes defined for the
9017  * reflection handle @obj. The objects.
9018  *
9019  * FIXME this function leaks like a sieve for SRE objects.
9020  */
9021 MonoCustomAttrInfo*
9022 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9023 {
9024         MonoClass *klass;
9025         MonoCustomAttrInfo *cinfo = NULL;
9026         
9027         klass = obj->vtable->klass;
9028         if (klass == mono_defaults.monotype_class) {
9029                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9030                 klass = mono_class_from_mono_type (type);
9031                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9032                 cinfo = mono_custom_attrs_from_class (klass);
9033         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9034                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9035                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9036         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9037                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9038                 cinfo = mono_custom_attrs_from_module (module->image);
9039         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9040                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9041                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9042         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9043                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9044                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9045         } else if (strcmp ("MonoField", klass->name) == 0) {
9046                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9047                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9048         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9049                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9050                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9051         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9052                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9053                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9054         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9055                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9056                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9057                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9058                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9059                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9060                 } else if (is_sr_mono_property (member_class)) {
9061                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9062                         MonoMethod *method;
9063                         if (!(method = prop->property->get))
9064                                 method = prop->property->set;
9065                         g_assert (method);
9066
9067                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9068                 } 
9069 #ifndef DISABLE_REFLECTION_EMIT
9070                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9071                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9072                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9073                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9074                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9075                         MonoMethod *method = NULL;
9076                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9077                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9078                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9079                                 method = ((MonoReflectionMethod *)c->cb)->method;
9080                         else
9081                                 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));
9082
9083                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9084                 } 
9085 #endif
9086                 else {
9087                         char *type_name = mono_type_get_full_name (member_class);
9088                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9089                         MonoException *ex = mono_get_exception_not_supported  (msg);
9090                         g_free (type_name);
9091                         g_free (msg);
9092                         mono_raise_exception (ex);
9093                 }
9094         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9095                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9096                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9097         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9098                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9099                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9100         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9101                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9102                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9103         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9104                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9105                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9106         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9107                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9108                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9109         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9110                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9111                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9112         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9113                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9114                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9115         } else { /* handle other types here... */
9116                 g_error ("get custom attrs not yet supported for %s", klass->name);
9117         }
9118
9119         return cinfo;
9120 }
9121
9122 /*
9123  * mono_reflection_get_custom_attrs_by_type:
9124  * @obj: a reflection object handle
9125  *
9126  * Return an array with all the custom attributes defined of the
9127  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9128  * of that type are returned. The objects are fully build. Return NULL if a loading error
9129  * occurs.
9130  */
9131 MonoArray*
9132 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9133 {
9134         MonoArray *result;
9135         MonoCustomAttrInfo *cinfo;
9136
9137         mono_error_init (error);
9138
9139         cinfo = mono_reflection_get_custom_attrs_info (obj);
9140         if (cinfo) {
9141                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9142                 if (!cinfo->cached)
9143                         mono_custom_attrs_free (cinfo);
9144         } else {
9145                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9146                 if (mono_loader_get_last_error ())
9147                         return NULL;
9148                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9149         }
9150
9151         return result;
9152 }
9153
9154 /*
9155  * mono_reflection_get_custom_attrs:
9156  * @obj: a reflection object handle
9157  *
9158  * Return an array with all the custom attributes defined of the
9159  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9160  * occurs.
9161  */
9162 MonoArray*
9163 mono_reflection_get_custom_attrs (MonoObject *obj)
9164 {
9165         MonoError error;
9166
9167         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9168 }
9169
9170 /*
9171  * mono_reflection_get_custom_attrs_data:
9172  * @obj: a reflection obj handle
9173  *
9174  * Returns an array of System.Reflection.CustomAttributeData,
9175  * which include information about attributes reflected on
9176  * types loaded using the Reflection Only methods
9177  */
9178 MonoArray*
9179 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9180 {
9181         MonoArray *result;
9182         MonoCustomAttrInfo *cinfo;
9183
9184         cinfo = mono_reflection_get_custom_attrs_info (obj);
9185         if (cinfo) {
9186                 result = mono_custom_attrs_data_construct (cinfo);
9187                 if (!cinfo->cached)
9188                         mono_custom_attrs_free (cinfo);
9189         } else
9190                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9191
9192         return result;
9193 }
9194
9195 static MonoReflectionType*
9196 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9197 {
9198         static MonoMethod *method_get_underlying_system_type = NULL;
9199         MonoMethod *usertype_method;
9200
9201         if (!method_get_underlying_system_type)
9202                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9203         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9204         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9205 }
9206
9207
9208 static gboolean
9209 is_corlib_type (MonoClass *class)
9210 {
9211         return class->image == mono_defaults.corlib;
9212 }
9213
9214 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9215         static MonoClass *cached_class; \
9216         if (cached_class) \
9217                 return cached_class == _class; \
9218         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9219                 cached_class = _class; \
9220                 return TRUE; \
9221         } \
9222         return FALSE; \
9223 } while (0) \
9224
9225
9226 #ifndef DISABLE_REFLECTION_EMIT
9227 static gboolean
9228 is_sre_array (MonoClass *class)
9229 {
9230         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9231 }
9232
9233 static gboolean
9234 is_sre_byref (MonoClass *class)
9235 {
9236         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9237 }
9238
9239 static gboolean
9240 is_sre_pointer (MonoClass *class)
9241 {
9242         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9243 }
9244
9245 static gboolean
9246 is_sre_generic_instance (MonoClass *class)
9247 {
9248         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9249 }
9250
9251 static gboolean
9252 is_sre_type_builder (MonoClass *class)
9253 {
9254         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9255 }
9256
9257 static gboolean
9258 is_sre_method_builder (MonoClass *class)
9259 {
9260         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9261 }
9262
9263 static gboolean
9264 is_sre_ctor_builder (MonoClass *class)
9265 {
9266         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9267 }
9268
9269 static gboolean
9270 is_sre_field_builder (MonoClass *class)
9271 {
9272         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9273 }
9274
9275 static gboolean
9276 is_sre_method_on_tb_inst (MonoClass *class)
9277 {
9278         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9279 }
9280
9281 static gboolean
9282 is_sre_ctor_on_tb_inst (MonoClass *class)
9283 {
9284         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9285 }
9286
9287 MonoType*
9288 mono_reflection_type_get_handle (MonoReflectionType* ref)
9289 {
9290         MonoClass *class;
9291         if (!ref)
9292                 return NULL;
9293         if (ref->type)
9294                 return ref->type;
9295
9296         if (is_usertype (ref)) {
9297                 ref = mono_reflection_type_get_underlying_system_type (ref);
9298                 if (ref == NULL || is_usertype (ref))
9299                         return NULL;
9300                 if (ref->type)
9301                         return ref->type;
9302         }
9303
9304         class = mono_object_class (ref);
9305
9306         if (is_sre_array (class)) {
9307                 MonoType *res;
9308                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9309                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9310                 g_assert (base);
9311                 if (sre_array->rank == 0) //single dimentional array
9312                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9313                 else
9314                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9315                 sre_array->type.type = res;
9316                 return res;
9317         } else if (is_sre_byref (class)) {
9318                 MonoType *res;
9319                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9320                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9321                 g_assert (base);
9322                 res = &mono_class_from_mono_type (base)->this_arg;
9323                 sre_byref->type.type = res;
9324                 return res;
9325         } else if (is_sre_pointer (class)) {
9326                 MonoType *res;
9327                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9328                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9329                 g_assert (base);
9330                 res = &mono_ptr_class_get (base)->byval_arg;
9331                 sre_pointer->type.type = res;
9332                 return res;
9333         } else if (is_sre_generic_instance (class)) {
9334                 MonoType *res, **types;
9335                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9336                 int i, count;
9337
9338                 count = mono_array_length (gclass->type_arguments);
9339                 types = g_new0 (MonoType*, count);
9340                 for (i = 0; i < count; ++i) {
9341                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9342                         types [i] = mono_reflection_type_get_handle (t);
9343                         if (!types[i]) {
9344                                 g_free (types);
9345                                 return NULL;
9346                         }
9347                 }
9348
9349                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9350                 g_free (types);
9351                 g_assert (res);
9352                 gclass->type.type = res;
9353                 return res;
9354         }
9355
9356         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9357         return NULL;
9358 }
9359
9360
9361
9362 void
9363 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9364 {
9365         mono_reflection_type_get_handle (type);
9366 }
9367
9368 void
9369 mono_reflection_register_with_runtime (MonoReflectionType *type)
9370 {
9371         MonoType *res = mono_reflection_type_get_handle (type);
9372         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9373         MonoClass *class;
9374
9375         if (!res)
9376                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9377
9378         class = mono_class_from_mono_type (res);
9379
9380         mono_loader_lock (); /*same locking as mono_type_get_object*/
9381         mono_domain_lock (domain);
9382
9383         if (!image_is_dynamic (class->image)) {
9384                 mono_class_setup_supertypes (class);
9385         } else {
9386                 if (!domain->type_hash)
9387                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9388                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9389                 mono_g_hash_table_insert (domain->type_hash, res, type);
9390         }
9391         mono_domain_unlock (domain);
9392         mono_loader_unlock ();
9393 }
9394
9395 /**
9396  * LOCKING: Assumes the loader lock is held.
9397  */
9398 static MonoMethodSignature*
9399 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9400         MonoMethodSignature *sig;
9401         int count, i;
9402
9403         count = parameters? mono_array_length (parameters): 0;
9404
9405         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9406         sig->param_count = count;
9407         sig->sentinelpos = -1; /* FIXME */
9408         for (i = 0; i < count; ++i)
9409                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9410         return sig;
9411 }
9412
9413 /**
9414  * LOCKING: Assumes the loader lock is held.
9415  */
9416 static MonoMethodSignature*
9417 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9418         MonoMethodSignature *sig;
9419
9420         sig = parameters_to_signature (image, ctor->parameters);
9421         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9422         sig->ret = &mono_defaults.void_class->byval_arg;
9423         return sig;
9424 }
9425
9426 /**
9427  * LOCKING: Assumes the loader lock is held.
9428  */
9429 static MonoMethodSignature*
9430 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9431         MonoMethodSignature *sig;
9432
9433         sig = parameters_to_signature (image, method->parameters);
9434         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9435         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9436         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9437         return sig;
9438 }
9439
9440 static MonoMethodSignature*
9441 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9442         MonoMethodSignature *sig;
9443
9444         sig = parameters_to_signature (NULL, method->parameters);
9445         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9446         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9447         sig->generic_param_count = 0;
9448         return sig;
9449 }
9450
9451 static void
9452 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9453 {
9454         MonoClass *klass = mono_object_class (prop);
9455         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9456                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9457                 *name = mono_string_to_utf8 (pb->name);
9458                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9459         } else {
9460                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9461                 *name = g_strdup (p->property->name);
9462                 if (p->property->get)
9463                         *type = mono_method_signature (p->property->get)->ret;
9464                 else
9465                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9466         }
9467 }
9468
9469 static void
9470 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9471 {
9472         MonoClass *klass = mono_object_class (field);
9473         if (strcmp (klass->name, "FieldBuilder") == 0) {
9474                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9475                 *name = mono_string_to_utf8 (fb->name);
9476                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9477         } else {
9478                 MonoReflectionField *f = (MonoReflectionField *)field;
9479                 *name = g_strdup (mono_field_get_name (f->field));
9480                 *type = f->field->type;
9481         }
9482 }
9483
9484 #else /* DISABLE_REFLECTION_EMIT */
9485
9486 void
9487 mono_reflection_register_with_runtime (MonoReflectionType *type)
9488 {
9489         /* This is empty */
9490 }
9491
9492 static gboolean
9493 is_sre_type_builder (MonoClass *class)
9494 {
9495         return FALSE;
9496 }
9497
9498 static gboolean
9499 is_sre_generic_instance (MonoClass *class)
9500 {
9501         return FALSE;
9502 }
9503
9504 static void
9505 init_type_builder_generics (MonoObject *type)
9506 {
9507 }
9508
9509 #endif /* !DISABLE_REFLECTION_EMIT */
9510
9511
9512 static gboolean
9513 is_sr_mono_field (MonoClass *class)
9514 {
9515         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9516 }
9517
9518 static gboolean
9519 is_sr_mono_property (MonoClass *class)
9520 {
9521         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9522 }
9523
9524 static gboolean
9525 is_sr_mono_method (MonoClass *class)
9526 {
9527         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9528 }
9529
9530 static gboolean
9531 is_sr_mono_cmethod (MonoClass *class)
9532 {
9533         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9534 }
9535
9536 static gboolean
9537 is_sr_mono_generic_method (MonoClass *class)
9538 {
9539         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9540 }
9541
9542 static gboolean
9543 is_sr_mono_generic_cmethod (MonoClass *class)
9544 {
9545         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9546 }
9547
9548 gboolean
9549 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9550 {
9551         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9552 }
9553
9554 static gboolean
9555 is_usertype (MonoReflectionType *ref)
9556 {
9557         MonoClass *class = mono_object_class (ref);
9558         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9559 }
9560
9561 static MonoReflectionType*
9562 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9563 {
9564         if (!type || type->type)
9565                 return type;
9566
9567         if (is_usertype (type)) {
9568                 type = mono_reflection_type_get_underlying_system_type (type);
9569                 if (is_usertype (type))
9570                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9571         }
9572
9573         return type;
9574 }
9575 /*
9576  * Encode a value in a custom attribute stream of bytes.
9577  * The value to encode is either supplied as an object in argument val
9578  * (valuetypes are boxed), or as a pointer to the data in the
9579  * argument argval.
9580  * @type represents the type of the value
9581  * @buffer is the start of the buffer
9582  * @p the current position in the buffer
9583  * @buflen contains the size of the buffer and is used to return the new buffer size
9584  * if this needs to be realloced.
9585  * @retbuffer and @retp return the start and the position of the buffer
9586  */
9587 static void
9588 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9589 {
9590         MonoTypeEnum simple_type;
9591         
9592         if ((p-buffer) + 10 >= *buflen) {
9593                 char *newbuf;
9594                 *buflen *= 2;
9595                 newbuf = g_realloc (buffer, *buflen);
9596                 p = newbuf + (p-buffer);
9597                 buffer = newbuf;
9598         }
9599         if (!argval)
9600                 argval = ((char*)arg + sizeof (MonoObject));
9601         simple_type = type->type;
9602 handle_enum:
9603         switch (simple_type) {
9604         case MONO_TYPE_BOOLEAN:
9605         case MONO_TYPE_U1:
9606         case MONO_TYPE_I1:
9607                 *p++ = *argval;
9608                 break;
9609         case MONO_TYPE_CHAR:
9610         case MONO_TYPE_U2:
9611         case MONO_TYPE_I2:
9612                 swap_with_size (p, argval, 2, 1);
9613                 p += 2;
9614                 break;
9615         case MONO_TYPE_U4:
9616         case MONO_TYPE_I4:
9617         case MONO_TYPE_R4:
9618                 swap_with_size (p, argval, 4, 1);
9619                 p += 4;
9620                 break;
9621         case MONO_TYPE_R8:
9622                 swap_with_size (p, argval, 8, 1);
9623                 p += 8;
9624                 break;
9625         case MONO_TYPE_U8:
9626         case MONO_TYPE_I8:
9627                 swap_with_size (p, argval, 8, 1);
9628                 p += 8;
9629                 break;
9630         case MONO_TYPE_VALUETYPE:
9631                 if (type->data.klass->enumtype) {
9632                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9633                         goto handle_enum;
9634                 } else {
9635                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9636                 }
9637                 break;
9638         case MONO_TYPE_STRING: {
9639                 char *str;
9640                 guint32 slen;
9641                 if (!arg) {
9642                         *p++ = 0xFF;
9643                         break;
9644                 }
9645                 str = mono_string_to_utf8 ((MonoString*)arg);
9646                 slen = strlen (str);
9647                 if ((p-buffer) + 10 + slen >= *buflen) {
9648                         char *newbuf;
9649                         *buflen *= 2;
9650                         *buflen += slen;
9651                         newbuf = g_realloc (buffer, *buflen);
9652                         p = newbuf + (p-buffer);
9653                         buffer = newbuf;
9654                 }
9655                 mono_metadata_encode_value (slen, p, &p);
9656                 memcpy (p, str, slen);
9657                 p += slen;
9658                 g_free (str);
9659                 break;
9660         }
9661         case MONO_TYPE_CLASS: {
9662                 char *str;
9663                 guint32 slen;
9664                 if (!arg) {
9665                         *p++ = 0xFF;
9666                         break;
9667                 }
9668 handle_type:
9669                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9670                 slen = strlen (str);
9671                 if ((p-buffer) + 10 + slen >= *buflen) {
9672                         char *newbuf;
9673                         *buflen *= 2;
9674                         *buflen += slen;
9675                         newbuf = g_realloc (buffer, *buflen);
9676                         p = newbuf + (p-buffer);
9677                         buffer = newbuf;
9678                 }
9679                 mono_metadata_encode_value (slen, p, &p);
9680                 memcpy (p, str, slen);
9681                 p += slen;
9682                 g_free (str);
9683                 break;
9684         }
9685         case MONO_TYPE_SZARRAY: {
9686                 int len, i;
9687                 MonoClass *eclass, *arg_eclass;
9688
9689                 if (!arg) {
9690                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9691                         break;
9692                 }
9693                 len = mono_array_length ((MonoArray*)arg);
9694                 *p++ = len & 0xff;
9695                 *p++ = (len >> 8) & 0xff;
9696                 *p++ = (len >> 16) & 0xff;
9697                 *p++ = (len >> 24) & 0xff;
9698                 *retp = p;
9699                 *retbuffer = buffer;
9700                 eclass = type->data.klass;
9701                 arg_eclass = mono_object_class (arg)->element_class;
9702
9703                 if (!eclass) {
9704                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9705                         eclass = mono_defaults.object_class;
9706                 }
9707                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9708                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9709                         int elsize = mono_class_array_element_size (arg_eclass);
9710                         for (i = 0; i < len; ++i) {
9711                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9712                                 elptr += elsize;
9713                         }
9714                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9715                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9716                         int elsize = mono_class_array_element_size (eclass);
9717                         for (i = 0; i < len; ++i) {
9718                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9719                                 elptr += elsize;
9720                         }
9721                 } else {
9722                         for (i = 0; i < len; ++i) {
9723                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9724                         }
9725                 }
9726                 break;
9727         }
9728         case MONO_TYPE_OBJECT: {
9729                 MonoClass *klass;
9730                 char *str;
9731                 guint32 slen;
9732
9733                 /*
9734                  * The parameter type is 'object' but the type of the actual
9735                  * argument is not. So we have to add type information to the blob
9736                  * too. This is completely undocumented in the spec.
9737                  */
9738
9739                 if (arg == NULL) {
9740                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9741                         *p++ = 0xFF;
9742                         break;
9743                 }
9744                 
9745                 klass = mono_object_class (arg);
9746
9747                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9748                         *p++ = 0x50;
9749                         goto handle_type;
9750                 } else if (klass->enumtype) {
9751                         *p++ = 0x55;
9752                 } else if (klass == mono_defaults.string_class) {
9753                         simple_type = MONO_TYPE_STRING;
9754                         *p++ = 0x0E;
9755                         goto handle_enum;
9756                 } else if (klass->rank == 1) {
9757                         *p++ = 0x1D;
9758                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9759                                 /* See Partition II, Appendix B3 */
9760                                 *p++ = 0x51;
9761                         else
9762                                 *p++ = klass->element_class->byval_arg.type;
9763                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9764                         break;
9765                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9766                         *p++ = simple_type = klass->byval_arg.type;
9767                         goto handle_enum;
9768                 } else {
9769                         g_error ("unhandled type in custom attr");
9770                 }
9771                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9772                 slen = strlen (str);
9773                 if ((p-buffer) + 10 + slen >= *buflen) {
9774                         char *newbuf;
9775                         *buflen *= 2;
9776                         *buflen += slen;
9777                         newbuf = g_realloc (buffer, *buflen);
9778                         p = newbuf + (p-buffer);
9779                         buffer = newbuf;
9780                 }
9781                 mono_metadata_encode_value (slen, p, &p);
9782                 memcpy (p, str, slen);
9783                 p += slen;
9784                 g_free (str);
9785                 simple_type = mono_class_enum_basetype (klass)->type;
9786                 goto handle_enum;
9787         }
9788         default:
9789                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9790         }
9791         *retp = p;
9792         *retbuffer = buffer;
9793 }
9794
9795 static void
9796 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9797 {
9798         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9799                 char *str = type_get_qualified_name (type, NULL);
9800                 int slen = strlen (str);
9801
9802                 *p++ = 0x55;
9803                 /*
9804                  * This seems to be optional...
9805                  * *p++ = 0x80;
9806                  */
9807                 mono_metadata_encode_value (slen, p, &p);
9808                 memcpy (p, str, slen);
9809                 p += slen;
9810                 g_free (str);
9811         } else if (type->type == MONO_TYPE_OBJECT) {
9812                 *p++ = 0x51;
9813         } else if (type->type == MONO_TYPE_CLASS) {
9814                 /* it should be a type: encode_cattr_value () has the check */
9815                 *p++ = 0x50;
9816         } else {
9817                 mono_metadata_encode_value (type->type, p, &p);
9818                 if (type->type == MONO_TYPE_SZARRAY)
9819                         /* See the examples in Partition VI, Annex B */
9820                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9821         }
9822
9823         *retp = p;
9824 }
9825
9826 #ifndef DISABLE_REFLECTION_EMIT
9827 static void
9828 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9829 {
9830         int len;
9831         /* Preallocate a large enough buffer */
9832         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9833                 char *str = type_get_qualified_name (type, NULL);
9834                 len = strlen (str);
9835                 g_free (str);
9836         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9837                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9838                 len = strlen (str);
9839                 g_free (str);
9840         } else {
9841                 len = 0;
9842         }
9843         len += strlen (name);
9844
9845         if ((p-buffer) + 20 + len >= *buflen) {
9846                 char *newbuf;
9847                 *buflen *= 2;
9848                 *buflen += len;
9849                 newbuf = g_realloc (buffer, *buflen);
9850                 p = newbuf + (p-buffer);
9851                 buffer = newbuf;
9852         }
9853
9854         encode_field_or_prop_type (type, p, &p);
9855
9856         len = strlen (name);
9857         mono_metadata_encode_value (len, p, &p);
9858         memcpy (p, name, len);
9859         p += len;
9860         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9861         *retp = p;
9862         *retbuffer = buffer;
9863 }
9864
9865 /*
9866  * mono_reflection_get_custom_attrs_blob:
9867  * @ctor: custom attribute constructor
9868  * @ctorArgs: arguments o the constructor
9869  * @properties:
9870  * @propValues:
9871  * @fields:
9872  * @fieldValues:
9873  * 
9874  * Creates the blob of data that needs to be saved in the metadata and that represents
9875  * the custom attributed described by @ctor, @ctorArgs etc.
9876  * Returns: a Byte array representing the blob of data.
9877  */
9878 MonoArray*
9879 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9880 {
9881         MonoArray *result;
9882         MonoMethodSignature *sig;
9883         MonoObject *arg;
9884         char *buffer, *p;
9885         guint32 buflen, i;
9886
9887         MONO_ARCH_SAVE_REGS;
9888
9889         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9890                 /* sig is freed later so allocate it in the heap */
9891                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9892         } else {
9893                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9894         }
9895
9896         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9897         buflen = 256;
9898         p = buffer = g_malloc (buflen);
9899         /* write the prolog */
9900         *p++ = 1;
9901         *p++ = 0;
9902         for (i = 0; i < sig->param_count; ++i) {
9903                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9904                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9905         }
9906         i = 0;
9907         if (properties)
9908                 i += mono_array_length (properties);
9909         if (fields)
9910                 i += mono_array_length (fields);
9911         *p++ = i & 0xff;
9912         *p++ = (i >> 8) & 0xff;
9913         if (properties) {
9914                 MonoObject *prop;
9915                 for (i = 0; i < mono_array_length (properties); ++i) {
9916                         MonoType *ptype;
9917                         char *pname;
9918
9919                         prop = mono_array_get (properties, gpointer, i);
9920                         get_prop_name_and_type (prop, &pname, &ptype);
9921                         *p++ = 0x54; /* PROPERTY signature */
9922                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9923                         g_free (pname);
9924                 }
9925         }
9926
9927         if (fields) {
9928                 MonoObject *field;
9929                 for (i = 0; i < mono_array_length (fields); ++i) {
9930                         MonoType *ftype;
9931                         char *fname;
9932
9933                         field = mono_array_get (fields, gpointer, i);
9934                         get_field_name_and_type (field, &fname, &ftype);
9935                         *p++ = 0x53; /* FIELD signature */
9936                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9937                         g_free (fname);
9938                 }
9939         }
9940
9941         g_assert (p - buffer <= buflen);
9942         buflen = p - buffer;
9943         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9944         p = mono_array_addr (result, char, 0);
9945         memcpy (p, buffer, buflen);
9946         g_free (buffer);
9947         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9948                 g_free (sig);
9949         return result;
9950 }
9951
9952 /*
9953  * mono_reflection_setup_internal_class:
9954  * @tb: a TypeBuilder object
9955  *
9956  * Creates a MonoClass that represents the TypeBuilder.
9957  * This is a trick that lets us simplify a lot of reflection code
9958  * (and will allow us to support Build and Run assemblies easier).
9959  */
9960 void
9961 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9962 {
9963         MonoError error;
9964         MonoClass *klass, *parent;
9965
9966         MONO_ARCH_SAVE_REGS;
9967
9968         RESOLVE_TYPE (tb->parent);
9969
9970         mono_loader_lock ();
9971
9972         if (tb->parent) {
9973                 /* check so we can compile corlib correctly */
9974                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9975                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9976                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9977                 } else {
9978                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9979                 }
9980         } else {
9981                 parent = NULL;
9982         }
9983         
9984         /* the type has already being created: it means we just have to change the parent */
9985         if (tb->type.type) {
9986                 klass = mono_class_from_mono_type (tb->type.type);
9987                 klass->parent = NULL;
9988                 /* fool mono_class_setup_parent */
9989                 klass->supertypes = NULL;
9990                 mono_class_setup_parent (klass, parent);
9991                 mono_class_setup_mono_type (klass);
9992                 mono_loader_unlock ();
9993                 return;
9994         }
9995
9996         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9997
9998         klass->image = &tb->module->dynamic_image->image;
9999
10000         klass->inited = 1; /* we lie to the runtime */
10001         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10002         if (!mono_error_ok (&error))
10003                 goto failure;
10004         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10005         if (!mono_error_ok (&error))
10006                 goto failure;
10007         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10008         klass->flags = tb->attrs;
10009         
10010         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10011
10012         klass->element_class = klass;
10013
10014         if (mono_class_get_ref_info (klass) == NULL) {
10015
10016                 mono_class_set_ref_info (klass, tb);
10017
10018                 /* Put into cache so mono_class_get_checked () will find it.
10019                 Skip nested types as those should not be available on the global scope. */
10020                 if (!tb->nesting_type)
10021                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10022
10023                 /*
10024                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10025                 by performing a mono_class_get which does the full resolution.
10026
10027                 Working around this semantics would require us to write a lot of code for no clear advantage.
10028                 */
10029                 mono_image_append_class_to_reflection_info_set (klass);
10030         } else {
10031                 g_assert (mono_class_get_ref_info (klass) == tb);
10032         }
10033
10034         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
10035                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
10036
10037         if (parent != NULL) {
10038                 mono_class_setup_parent (klass, parent);
10039         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10040                 const char *old_n = klass->name;
10041                 /* trick to get relative numbering right when compiling corlib */
10042                 klass->name = "BuildingObject";
10043                 mono_class_setup_parent (klass, mono_defaults.object_class);
10044                 klass->name = old_n;
10045         }
10046
10047         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10048                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10049                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10050                 klass->instance_size = sizeof (MonoObject);
10051                 klass->size_inited = 1;
10052                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10053         }
10054
10055         mono_class_setup_mono_type (klass);
10056
10057         mono_class_setup_supertypes (klass);
10058
10059         /*
10060          * FIXME: handle interfaces.
10061          */
10062
10063         tb->type.type = &klass->byval_arg;
10064
10065         if (tb->nesting_type) {
10066                 g_assert (tb->nesting_type->type);
10067                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10068         }
10069
10070         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10071
10072         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10073         
10074         mono_loader_unlock ();
10075         return;
10076
10077 failure:
10078         mono_loader_unlock ();
10079         mono_error_raise_exception (&error);
10080 }
10081
10082 /*
10083  * mono_reflection_setup_generic_class:
10084  * @tb: a TypeBuilder object
10085  *
10086  * Setup the generic class before adding the first generic parameter.
10087  */
10088 void
10089 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10090 {
10091 }
10092
10093 /*
10094  * mono_reflection_create_generic_class:
10095  * @tb: a TypeBuilder object
10096  *
10097  * Creates the generic class after all generic parameters have been added.
10098  */
10099 void
10100 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10101 {
10102         MonoClass *klass;
10103         int count, i;
10104
10105         MONO_ARCH_SAVE_REGS;
10106
10107         klass = mono_class_from_mono_type (tb->type.type);
10108
10109         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10110
10111         if (klass->generic_container || (count == 0))
10112                 return;
10113
10114         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10115
10116         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10117
10118         klass->generic_container->owner.klass = klass;
10119         klass->generic_container->type_argc = count;
10120         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10121
10122         klass->is_generic = 1;
10123
10124         for (i = 0; i < count; i++) {
10125                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10126                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10127                 klass->generic_container->type_params [i] = *param;
10128                 /*Make sure we are a diferent type instance */
10129                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10130                 klass->generic_container->type_params [i].info.pklass = NULL;
10131                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10132
10133                 g_assert (klass->generic_container->type_params [i].param.owner);
10134         }
10135
10136         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10137 }
10138
10139 /*
10140  * mono_reflection_create_internal_class:
10141  * @tb: a TypeBuilder object
10142  *
10143  * Actually create the MonoClass that is associated with the TypeBuilder.
10144  */
10145 void
10146 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10147 {
10148         MonoClass *klass;
10149
10150         MONO_ARCH_SAVE_REGS;
10151
10152         klass = mono_class_from_mono_type (tb->type.type);
10153
10154         mono_loader_lock ();
10155         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10156                 MonoReflectionFieldBuilder *fb;
10157                 MonoClass *ec;
10158                 MonoType *enum_basetype;
10159
10160                 g_assert (tb->fields != NULL);
10161                 g_assert (mono_array_length (tb->fields) >= 1);
10162
10163                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10164
10165                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10166                         mono_loader_unlock ();
10167                         return;
10168                 }
10169
10170                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10171                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10172                 if (!klass->element_class)
10173                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10174
10175                 /*
10176                  * get the element_class from the current corlib.
10177                  */
10178                 ec = default_class_from_mono_type (enum_basetype);
10179                 klass->instance_size = ec->instance_size;
10180                 klass->size_inited = 1;
10181                 /* 
10182                  * this is almost safe to do with enums and it's needed to be able
10183                  * to create objects of the enum type (for use in SetConstant).
10184                  */
10185                 /* FIXME: Does this mean enums can't have method overrides ? */
10186                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10187         }
10188         mono_loader_unlock ();
10189 }
10190
10191 static MonoMarshalSpec*
10192 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10193                                                                 MonoReflectionMarshal *minfo)
10194 {
10195         MonoMarshalSpec *res;
10196
10197         res = image_g_new0 (image, MonoMarshalSpec, 1);
10198         res->native = minfo->type;
10199
10200         switch (minfo->type) {
10201         case MONO_NATIVE_LPARRAY:
10202                 res->data.array_data.elem_type = minfo->eltype;
10203                 if (minfo->has_size) {
10204                         res->data.array_data.param_num = minfo->param_num;
10205                         res->data.array_data.num_elem = minfo->count;
10206                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10207                 }
10208                 else {
10209                         res->data.array_data.param_num = -1;
10210                         res->data.array_data.num_elem = -1;
10211                         res->data.array_data.elem_mult = -1;
10212                 }
10213                 break;
10214
10215         case MONO_NATIVE_BYVALTSTR:
10216         case MONO_NATIVE_BYVALARRAY:
10217                 res->data.array_data.num_elem = minfo->count;
10218                 break;
10219
10220         case MONO_NATIVE_CUSTOM:
10221                 if (minfo->marshaltyperef)
10222                         res->data.custom_data.custom_name =
10223                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10224                 if (minfo->mcookie)
10225                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10226                 break;
10227
10228         default:
10229                 break;
10230         }
10231
10232         return res;
10233 }
10234 #endif /* !DISABLE_REFLECTION_EMIT */
10235
10236 MonoReflectionMarshalAsAttribute*
10237 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10238                                                                                    MonoMarshalSpec *spec)
10239 {
10240         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10241         MonoReflectionMarshalAsAttribute *minfo;
10242         MonoType *mtype;
10243
10244         if (!System_Reflection_Emit_MarshalAsAttribute) {
10245                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10246                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10247                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10248         }
10249
10250         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10251         minfo->utype = spec->native;
10252
10253         switch (minfo->utype) {
10254         case MONO_NATIVE_LPARRAY:
10255                 minfo->array_subtype = spec->data.array_data.elem_type;
10256                 minfo->size_const = spec->data.array_data.num_elem;
10257                 if (spec->data.array_data.param_num != -1)
10258                         minfo->size_param_index = spec->data.array_data.param_num;
10259                 break;
10260
10261         case MONO_NATIVE_BYVALTSTR:
10262         case MONO_NATIVE_BYVALARRAY:
10263                 minfo->size_const = spec->data.array_data.num_elem;
10264                 break;
10265
10266         case MONO_NATIVE_CUSTOM:
10267                 if (spec->data.custom_data.custom_name) {
10268                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10269                         if (mtype)
10270                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10271
10272                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10273                 }
10274                 if (spec->data.custom_data.cookie)
10275                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10276                 break;
10277
10278         default:
10279                 break;
10280         }
10281
10282         return minfo;
10283 }
10284
10285 #ifndef DISABLE_REFLECTION_EMIT
10286 static MonoMethod*
10287 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10288                                          ReflectionMethodBuilder *rmb,
10289                                          MonoMethodSignature *sig)
10290 {
10291         MonoError error;
10292         MonoMethod *m;
10293         MonoMethodWrapper *wrapperm;
10294         MonoMarshalSpec **specs;
10295         MonoReflectionMethodAux *method_aux;
10296         MonoImage *image;
10297         gboolean dynamic;
10298         int i;
10299
10300         mono_error_init (&error);
10301         /*
10302          * Methods created using a MethodBuilder should have their memory allocated
10303          * inside the image mempool, while dynamic methods should have their memory
10304          * malloc'd.
10305          */
10306         dynamic = rmb->refs != NULL;
10307         image = dynamic ? NULL : klass->image;
10308
10309         if (!dynamic)
10310                 g_assert (!klass->generic_class);
10311
10312         mono_loader_lock ();
10313
10314         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10315                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10316                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10317         else
10318                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10319
10320         wrapperm = (MonoMethodWrapper*)m;
10321
10322         m->dynamic = dynamic;
10323         m->slot = -1;
10324         m->flags = rmb->attrs;
10325         m->iflags = rmb->iattrs;
10326         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10327         m->klass = klass;
10328         m->signature = sig;
10329         m->sre_method = TRUE;
10330         m->skip_visibility = rmb->skip_visibility;
10331         if (rmb->table_idx)
10332                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10333
10334         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10335                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10336                         m->string_ctor = 1;
10337
10338                 m->signature->pinvoke = 1;
10339         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10340                 m->signature->pinvoke = 1;
10341
10342                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10343
10344                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10345                 g_assert (mono_error_ok (&error));
10346                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10347                 g_assert (mono_error_ok (&error));
10348                 
10349                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10350
10351                 if (image_is_dynamic (klass->image))
10352                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10353
10354                 mono_loader_unlock ();
10355
10356                 return m;
10357         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10358                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10359                 MonoMethodHeader *header;
10360                 guint32 code_size;
10361                 gint32 max_stack, i;
10362                 gint32 num_locals = 0;
10363                 gint32 num_clauses = 0;
10364                 guint8 *code;
10365
10366                 if (rmb->ilgen) {
10367                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10368                         code_size = rmb->ilgen->code_len;
10369                         max_stack = rmb->ilgen->max_stack;
10370                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10371                         if (rmb->ilgen->ex_handlers)
10372                                 num_clauses = method_count_clauses (rmb->ilgen);
10373                 } else {
10374                         if (rmb->code) {
10375                                 code = mono_array_addr (rmb->code, guint8, 0);
10376                                 code_size = mono_array_length (rmb->code);
10377                                 /* we probably need to run a verifier on the code... */
10378                                 max_stack = 8; 
10379                         }
10380                         else {
10381                                 code = NULL;
10382                                 code_size = 0;
10383                                 max_stack = 8;
10384                         }
10385                 }
10386
10387                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10388                 header->code_size = code_size;
10389                 header->code = image_g_malloc (image, code_size);
10390                 memcpy ((char*)header->code, code, code_size);
10391                 header->max_stack = max_stack;
10392                 header->init_locals = rmb->init_locals;
10393                 header->num_locals = num_locals;
10394
10395                 for (i = 0; i < num_locals; ++i) {
10396                         MonoReflectionLocalBuilder *lb = 
10397                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10398
10399                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10400                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10401                 }
10402
10403                 header->num_clauses = num_clauses;
10404                 if (num_clauses) {
10405                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10406                                  rmb->ilgen, num_clauses);
10407                 }
10408
10409                 wrapperm->header = header;
10410         }
10411
10412         if (rmb->generic_params) {
10413                 int count = mono_array_length (rmb->generic_params);
10414                 MonoGenericContainer *container = rmb->generic_container;
10415
10416                 g_assert (container);
10417
10418                 container->type_argc = count;
10419                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10420                 container->owner.method = m;
10421
10422                 m->is_generic = TRUE;
10423                 mono_method_set_generic_container (m, container);
10424
10425                 for (i = 0; i < count; i++) {
10426                         MonoReflectionGenericParam *gp =
10427                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10428                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10429                         container->type_params [i] = *param;
10430                 }
10431
10432                 /*
10433                  * The method signature might have pointers to generic parameters that belong to other methods.
10434                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10435                  * generic parameters.
10436                  */
10437                 for (i = 0; i < m->signature->param_count; ++i) {
10438                         MonoType *t = m->signature->params [i];
10439                         if (t->type == MONO_TYPE_MVAR) {
10440                                 MonoGenericParam *gparam =  t->data.generic_param;
10441                                 if (gparam->num < count) {
10442                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10443                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10444                                 }
10445
10446                         }
10447                 }
10448
10449                 if (klass->generic_container) {
10450                         container->parent = klass->generic_container;
10451                         container->context.class_inst = klass->generic_container->context.class_inst;
10452                 }
10453                 container->context.method_inst = mono_get_shared_generic_inst (container);
10454         }
10455
10456         if (rmb->refs) {
10457                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10458                 int i;
10459                 void **data;
10460
10461                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10462
10463                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10464                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10465                 for (i = 0; i < rmb->nrefs; ++i)
10466                         data [i + 1] = rmb->refs [i];
10467         }
10468
10469         method_aux = NULL;
10470
10471         /* Parameter info */
10472         if (rmb->pinfo) {
10473                 if (!method_aux)
10474                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10475                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10476                 for (i = 0; i <= m->signature->param_count; ++i) {
10477                         MonoReflectionParamBuilder *pb;
10478                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10479                                 if ((i > 0) && (pb->attrs)) {
10480                                         /* Make a copy since it might point to a shared type structure */
10481                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10482                                         m->signature->params [i - 1]->attrs = pb->attrs;
10483                                 }
10484
10485                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10486                                         MonoDynamicImage *assembly;
10487                                         guint32 idx, def_type, len;
10488                                         char *p;
10489                                         const char *p2;
10490
10491                                         if (!method_aux->param_defaults) {
10492                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10493                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10494                                         }
10495                                         assembly = (MonoDynamicImage*)klass->image;
10496                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10497                                         /* Copy the data from the blob since it might get realloc-ed */
10498                                         p = assembly->blob.data + idx;
10499                                         len = mono_metadata_decode_blob_size (p, &p2);
10500                                         len += p2 - p;
10501                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10502                                         method_aux->param_default_types [i] = def_type;
10503                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10504                                 }
10505
10506                                 if (pb->name) {
10507                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10508                                         g_assert (mono_error_ok (&error));
10509                                 }
10510                                 if (pb->cattrs) {
10511                                         if (!method_aux->param_cattr)
10512                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10513                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10514                                 }
10515                         }
10516                 }
10517         }
10518
10519         /* Parameter marshalling */
10520         specs = NULL;
10521         if (rmb->pinfo)         
10522                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10523                         MonoReflectionParamBuilder *pb;
10524                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10525                                 if (pb->marshal_info) {
10526                                         if (specs == NULL)
10527                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10528                                         specs [pb->position] = 
10529                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10530                                 }
10531                         }
10532                 }
10533         if (specs != NULL) {
10534                 if (!method_aux)
10535                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10536                 method_aux->param_marshall = specs;
10537         }
10538
10539         if (image_is_dynamic (klass->image) && method_aux)
10540                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10541
10542         mono_loader_unlock ();
10543
10544         return m;
10545 }       
10546
10547 static MonoMethod*
10548 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10549 {
10550         ReflectionMethodBuilder rmb;
10551         MonoMethodSignature *sig;
10552
10553         mono_loader_lock ();
10554         sig = ctor_builder_to_signature (klass->image, mb);
10555         mono_loader_unlock ();
10556
10557         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10558
10559         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10560         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10561
10562         /* If we are in a generic class, we might be called multiple times from inflate_method */
10563         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10564                 /* ilgen is no longer needed */
10565                 mb->ilgen = NULL;
10566         }
10567
10568         return mb->mhandle;
10569 }
10570
10571 static MonoMethod*
10572 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10573 {
10574         ReflectionMethodBuilder rmb;
10575         MonoMethodSignature *sig;
10576
10577         mono_loader_lock ();
10578         sig = method_builder_to_signature (klass->image, mb);
10579         mono_loader_unlock ();
10580
10581         reflection_methodbuilder_from_method_builder (&rmb, mb);
10582
10583         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10584         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10585
10586         /* If we are in a generic class, we might be called multiple times from inflate_method */
10587         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10588                 /* ilgen is no longer needed */
10589                 mb->ilgen = NULL;
10590         }
10591         return mb->mhandle;
10592 }
10593
10594 static MonoClassField*
10595 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10596 {
10597         MonoClassField *field;
10598         MonoType *custom;
10599         MonoError error;
10600
10601         field = g_new0 (MonoClassField, 1);
10602
10603         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10604         g_assert (mono_error_ok (&error));
10605         if (fb->attrs || fb->modreq || fb->modopt) {
10606                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10607                 field->type->attrs = fb->attrs;
10608
10609                 g_assert (image_is_dynamic (klass->image));
10610                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10611                 g_free (field->type);
10612                 field->type = mono_metadata_type_dup (klass->image, custom);
10613                 g_free (custom);
10614         } else {
10615                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10616         }
10617         if (fb->offset != -1)
10618                 field->offset = fb->offset;
10619         field->parent = klass;
10620         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10621
10622         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10623
10624         return field;
10625 }
10626 #endif
10627
10628 MonoType*
10629 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10630 {
10631         MonoClass *klass;
10632         MonoReflectionTypeBuilder *tb = NULL;
10633         gboolean is_dynamic = FALSE;
10634         MonoDomain *domain;
10635         MonoClass *geninst;
10636
10637         mono_loader_lock ();
10638
10639         domain = mono_object_domain (type);
10640
10641         if (is_sre_type_builder (mono_object_class (type))) {
10642                 tb = (MonoReflectionTypeBuilder *) type;
10643
10644                 is_dynamic = TRUE;
10645         } else if (is_sre_generic_instance (mono_object_class (type))) {
10646                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10647                 MonoReflectionType *gtd = rgi->generic_type;
10648
10649                 if (is_sre_type_builder (mono_object_class (gtd))) {
10650                         tb = (MonoReflectionTypeBuilder *)gtd;
10651                         is_dynamic = TRUE;
10652                 }
10653         }
10654
10655         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10656         if (tb && tb->generic_container)
10657                 mono_reflection_create_generic_class (tb);
10658
10659         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10660         if (!klass->generic_container) {
10661                 mono_loader_unlock ();
10662                 return NULL;
10663         }
10664
10665         if (klass->wastypebuilder) {
10666                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10667
10668                 is_dynamic = TRUE;
10669         }
10670
10671         mono_loader_unlock ();
10672
10673         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10674
10675         return &geninst->byval_arg;
10676 }
10677
10678 MonoClass*
10679 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10680 {
10681         MonoGenericClass *gclass;
10682         MonoGenericInst *inst;
10683
10684         g_assert (klass->generic_container);
10685
10686         inst = mono_metadata_get_generic_inst (type_argc, types);
10687         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10688
10689         return mono_generic_class_get_class (gclass);
10690 }
10691
10692 MonoReflectionMethod*
10693 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10694 {
10695         MonoClass *klass;
10696         MonoMethod *method, *inflated;
10697         MonoMethodInflated *imethod;
10698         MonoGenericContext tmp_context;
10699         MonoGenericInst *ginst;
10700         MonoType **type_argv;
10701         int count, i;
10702
10703         MONO_ARCH_SAVE_REGS;
10704
10705         /*FIXME but this no longer should happen*/
10706         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10707 #ifndef DISABLE_REFLECTION_EMIT
10708                 MonoReflectionMethodBuilder *mb = NULL;
10709                 MonoReflectionTypeBuilder *tb;
10710                 MonoClass *klass;
10711
10712                 mb = (MonoReflectionMethodBuilder *) rmethod;
10713                 tb = (MonoReflectionTypeBuilder *) mb->type;
10714                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10715
10716                 method = methodbuilder_to_mono_method (klass, mb);
10717 #else
10718                 g_assert_not_reached ();
10719                 method = NULL;
10720 #endif
10721         } else {
10722                 method = rmethod->method;
10723         }
10724
10725         klass = method->klass;
10726
10727         if (method->is_inflated)
10728                 method = ((MonoMethodInflated *) method)->declaring;
10729
10730         count = mono_method_signature (method)->generic_param_count;
10731         if (count != mono_array_length (types))
10732                 return NULL;
10733
10734         type_argv = g_new0 (MonoType *, count);
10735         for (i = 0; i < count; i++) {
10736                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10737                 type_argv [i] = mono_reflection_type_get_handle (garg);
10738         }
10739         ginst = mono_metadata_get_generic_inst (count, type_argv);
10740         g_free (type_argv);
10741
10742         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10743         tmp_context.method_inst = ginst;
10744
10745         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10746         imethod = (MonoMethodInflated *) inflated;
10747
10748         /*FIXME but I think this is no longer necessary*/
10749         if (image_is_dynamic (method->klass->image)) {
10750                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10751                 /*
10752                  * This table maps metadata structures representing inflated methods/fields
10753                  * to the reflection objects representing their generic definitions.
10754                  */
10755                 mono_image_lock ((MonoImage*)image);
10756                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10757                 mono_image_unlock ((MonoImage*)image);
10758         }
10759
10760         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10761                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10762         
10763         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10764 }
10765
10766 #ifndef DISABLE_REFLECTION_EMIT
10767
10768 static MonoMethod *
10769 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10770 {
10771         MonoMethodInflated *imethod;
10772         MonoGenericContext *context;
10773         int i;
10774
10775         /*
10776          * With generic code sharing the klass might not be inflated.
10777          * This can happen because classes inflated with their own
10778          * type arguments are "normalized" to the uninflated class.
10779          */
10780         if (!klass->generic_class)
10781                 return method;
10782
10783         context = mono_class_get_context (klass);
10784
10785         if (klass->method.count && klass->methods) {
10786                 /* Find the already created inflated method */
10787                 for (i = 0; i < klass->method.count; ++i) {
10788                         g_assert (klass->methods [i]->is_inflated);
10789                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10790                                 break;
10791                 }
10792                 g_assert (i < klass->method.count);
10793                 imethod = (MonoMethodInflated*)klass->methods [i];
10794         } else {
10795                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10796         }
10797
10798         if (method->is_generic && image_is_dynamic (method->klass->image)) {
10799                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10800
10801                 mono_image_lock ((MonoImage*)image);
10802                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10803                 mono_image_unlock ((MonoImage*)image);
10804         }
10805         return (MonoMethod *) imethod;
10806 }
10807
10808 static MonoMethod *
10809 inflate_method (MonoReflectionType *type, MonoObject *obj)
10810 {
10811         MonoMethod *method;
10812         MonoClass *gklass;
10813
10814         MonoClass *type_class = mono_object_class (type);
10815
10816         if (is_sre_generic_instance (type_class)) {
10817                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10818                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10819         } else if (is_sre_type_builder (type_class)) {
10820                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10821         } else if (type->type) {
10822                 gklass = mono_class_from_mono_type (type->type);
10823                 gklass = mono_class_get_generic_type_definition (gklass);
10824         } else {
10825                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10826         }
10827
10828         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10829                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10830                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10831                 else
10832                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10833         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10834                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10835         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10836                 method = ((MonoReflectionMethod *) obj)->method;
10837         else {
10838                 method = NULL; /* prevent compiler warning */
10839                 g_error ("can't handle type %s", obj->vtable->klass->name);
10840         }
10841
10842         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10843 }
10844
10845 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10846 void
10847 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10848 {
10849         MonoGenericClass *gclass;
10850         MonoDynamicGenericClass *dgclass;
10851         MonoClass *klass, *gklass;
10852         MonoType *gtype;
10853         int i;
10854
10855         MONO_ARCH_SAVE_REGS;
10856
10857         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10858         klass = mono_class_from_mono_type (gtype);
10859         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10860         gclass = gtype->data.generic_class;
10861
10862         if (!gclass->is_dynamic)
10863                 return;
10864
10865         dgclass = (MonoDynamicGenericClass *) gclass;
10866
10867         if (dgclass->initialized)
10868                 return;
10869
10870         gklass = gclass->container_class;
10871         mono_class_init (gklass);
10872
10873         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10874
10875         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10876         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10877         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10878
10879         for (i = 0; i < dgclass->count_fields; i++) {
10880                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10881                 MonoClassField *field, *inflated_field = NULL;
10882
10883                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10884                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10885                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10886                         field = ((MonoReflectionField *) obj)->field;
10887                 else {
10888                         field = NULL; /* prevent compiler warning */
10889                         g_assert_not_reached ();
10890                 }
10891
10892                 dgclass->fields [i] = *field;
10893                 dgclass->fields [i].parent = klass;
10894                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10895                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10896                 dgclass->field_generic_types [i] = field->type;
10897                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10898                 dgclass->field_objects [i] = obj;
10899
10900                 if (inflated_field) {
10901                         g_free (inflated_field);
10902                 } else {
10903                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10904                 }
10905         }
10906
10907         dgclass->initialized = TRUE;
10908 }
10909
10910 void
10911 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10912 {
10913         MonoDynamicGenericClass *dgclass;
10914         int i;
10915
10916         g_assert (gclass->is_dynamic);
10917
10918         dgclass = (MonoDynamicGenericClass *)gclass;
10919
10920         for (i = 0; i < dgclass->count_fields; ++i) {
10921                 MonoClassField *field = dgclass->fields + i;
10922                 mono_metadata_free_type (field->type);
10923                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10924         }
10925 }
10926
10927 static void
10928 fix_partial_generic_class (MonoClass *klass)
10929 {
10930         MonoClass *gklass = klass->generic_class->container_class;
10931         MonoDynamicGenericClass *dgclass;
10932         int i;
10933
10934         if (klass->wastypebuilder)
10935                 return;
10936
10937         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10938         if (klass->parent != gklass->parent) {
10939                 MonoError error;
10940                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10941                 if (mono_error_ok (&error)) {
10942                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10943                         mono_metadata_free_type (parent_type);
10944                         if (parent != klass->parent) {
10945                                 /*fool mono_class_setup_parent*/
10946                                 klass->supertypes = NULL;
10947                                 mono_class_setup_parent (klass, parent);
10948                         }
10949                 } else {
10950                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10951                         mono_error_cleanup (&error);
10952                         if (gklass->wastypebuilder)
10953                                 klass->wastypebuilder = TRUE;
10954                         return;
10955                 }
10956         }
10957
10958         if (!dgclass->initialized)
10959                 return;
10960
10961         if (klass->method.count != gklass->method.count) {
10962                 klass->method.count = gklass->method.count;
10963                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10964
10965                 for (i = 0; i < klass->method.count; i++) {
10966                         klass->methods [i] = mono_class_inflate_generic_method_full (
10967                                 gklass->methods [i], klass, mono_class_get_context (klass));
10968                 }
10969         }
10970
10971         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10972                 klass->interface_count = gklass->interface_count;
10973                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10974                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10975
10976                 for (i = 0; i < gklass->interface_count; ++i) {
10977                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10978                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10979                         mono_metadata_free_type (iface_type);
10980
10981                         ensure_runtime_vtable (klass->interfaces [i]);
10982                 }
10983                 klass->interfaces_inited = 1;
10984         }
10985
10986         if (klass->field.count != gklass->field.count) {
10987                 klass->field.count = gklass->field.count;
10988                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10989
10990                 for (i = 0; i < klass->field.count; i++) {
10991                         klass->fields [i] = gklass->fields [i];
10992                         klass->fields [i].parent = klass;
10993                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10994                 }
10995         }
10996
10997         /*We can only finish with this klass once it's parent has as well*/
10998         if (gklass->wastypebuilder)
10999                 klass->wastypebuilder = TRUE;
11000         return;
11001 }
11002
11003 static void
11004 ensure_generic_class_runtime_vtable (MonoClass *klass)
11005 {
11006         MonoClass *gklass = klass->generic_class->container_class;
11007
11008         ensure_runtime_vtable (gklass); 
11009
11010         fix_partial_generic_class (klass);
11011 }
11012
11013 static void
11014 ensure_runtime_vtable (MonoClass *klass)
11015 {
11016         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11017         int i, num, j;
11018
11019         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11020                 return;
11021         if (klass->parent)
11022                 ensure_runtime_vtable (klass->parent);
11023
11024         if (tb) {
11025                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11026                 num += tb->num_methods;
11027                 klass->method.count = num;
11028                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11029                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11030                 for (i = 0; i < num; ++i)
11031                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11032                 num = tb->num_methods;
11033                 j = i;
11034                 for (i = 0; i < num; ++i)
11035                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11036         
11037                 if (tb->interfaces) {
11038                         klass->interface_count = mono_array_length (tb->interfaces);
11039                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11040                         for (i = 0; i < klass->interface_count; ++i) {
11041                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11042                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11043                                 ensure_runtime_vtable (klass->interfaces [i]);
11044                         }
11045                         klass->interfaces_inited = 1;
11046                 }
11047         } else if (klass->generic_class){
11048                 ensure_generic_class_runtime_vtable (klass);
11049         }
11050
11051         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11052                 int slot_num = 0;
11053                 for (i = 0; i < klass->method.count; ++i) {
11054                         MonoMethod *im = klass->methods [i];
11055                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11056                                 im->slot = slot_num++;
11057                 }
11058                 
11059                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11060                 mono_class_setup_interface_offsets (klass);
11061                 mono_class_setup_interface_id (klass);
11062         }
11063
11064         /*
11065          * The generic vtable is needed even if image->run is not set since some
11066          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11067          * method->slot being defined.
11068          */
11069
11070         /* 
11071          * tb->methods could not be freed since it is used for determining 
11072          * overrides during dynamic vtable construction.
11073          */
11074 }
11075
11076 static MonoMethod*
11077 mono_reflection_method_get_handle (MonoObject *method)
11078 {
11079         MonoClass *class = mono_object_class (method);
11080         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11081                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11082                 return sr_method->method;
11083         }
11084         if (is_sre_method_builder (class)) {
11085                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11086                 return mb->mhandle;
11087         }
11088         if (is_sre_method_on_tb_inst (class)) {
11089                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11090                 MonoMethod *result;
11091                 /*FIXME move this to a proper method and unify with resolve_object*/
11092                 if (m->method_args) {
11093                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11094                 } else {
11095                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11096                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11097                         MonoMethod *mono_method;
11098
11099                         if (is_sre_method_builder (mono_object_class (m->mb)))
11100                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11101                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11102                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11103                         else
11104                                 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)));
11105
11106                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11107                 }
11108                 return result;
11109         }
11110
11111         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11112         return NULL;
11113 }
11114
11115 void
11116 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11117 {
11118         MonoReflectionTypeBuilder *tb;
11119         int i, j, onum;
11120         MonoReflectionMethod *m;
11121
11122         *overrides = NULL;
11123         *num_overrides = 0;
11124
11125         g_assert (image_is_dynamic (klass->image));
11126
11127         if (!mono_class_get_ref_info (klass))
11128                 return;
11129
11130         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11131
11132         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11133
11134         onum = 0;
11135         if (tb->methods) {
11136                 for (i = 0; i < tb->num_methods; ++i) {
11137                         MonoReflectionMethodBuilder *mb = 
11138                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11139                         if (mb->override_methods)
11140                                 onum += mono_array_length (mb->override_methods);
11141                 }
11142         }
11143
11144         if (onum) {
11145                 *overrides = g_new0 (MonoMethod*, onum * 2);
11146
11147                 onum = 0;
11148                 for (i = 0; i < tb->num_methods; ++i) {
11149                         MonoReflectionMethodBuilder *mb = 
11150                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11151                         if (mb->override_methods) {
11152                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11153                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11154
11155                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11156                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11157
11158                                         g_assert (mb->mhandle);
11159
11160                                         onum ++;
11161                                 }
11162                         }
11163                 }
11164         }
11165
11166         *num_overrides = onum;
11167 }
11168
11169 static void
11170 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11171 {
11172         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11173         MonoReflectionFieldBuilder *fb;
11174         MonoClassField *field;
11175         MonoImage *image = klass->image;
11176         const char *p, *p2;
11177         int i;
11178         guint32 len, idx, real_size = 0;
11179
11180         klass->field.count = tb->num_fields;
11181         klass->field.first = 0;
11182
11183         mono_error_init (error);
11184
11185         if (tb->class_size) {
11186                 if ((tb->packing_size & 0xfffffff0) != 0) {
11187                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
11188                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11189                         return;
11190                 }
11191                 klass->packing_size = tb->packing_size;
11192                 real_size = klass->instance_size + tb->class_size;
11193         }
11194
11195         if (!klass->field.count) {
11196                 klass->instance_size = MAX (klass->instance_size, real_size);
11197                 return;
11198         }
11199         
11200         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11201         mono_class_alloc_ext (klass);
11202         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11203         /*
11204         This is, guess what, a hack.
11205         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11206         On the static path no field class is resolved, only types are built. This is the right thing to do
11207         but we suck.
11208         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11209         */
11210         klass->size_inited = 1;
11211
11212         for (i = 0; i < klass->field.count; ++i) {
11213                 MonoArray *rva_data;
11214                 fb = mono_array_get (tb->fields, gpointer, i);
11215                 field = &klass->fields [i];
11216                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11217                 if (!mono_error_ok (error))
11218                         return;
11219                 if (fb->attrs) {
11220                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11221                         field->type->attrs = fb->attrs;
11222                 } else {
11223                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11224                 }
11225
11226                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11227                         char *base = mono_array_addr (rva_data, char, 0);
11228                         size_t size = mono_array_length (rva_data);
11229                         char *data = mono_image_alloc (klass->image, size);
11230                         memcpy (data, base, size);
11231                         klass->ext->field_def_values [i].data = data;
11232                 }
11233                 if (fb->offset != -1)
11234                         field->offset = fb->offset;
11235                 field->parent = klass;
11236                 fb->handle = field;
11237                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11238
11239                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11240                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11241                 }
11242                 if (fb->def_value) {
11243                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11244                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11245                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11246                         /* Copy the data from the blob since it might get realloc-ed */
11247                         p = assembly->blob.data + idx;
11248                         len = mono_metadata_decode_blob_size (p, &p2);
11249                         len += p2 - p;
11250                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11251                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11252                 }
11253         }
11254
11255         klass->instance_size = MAX (klass->instance_size, real_size);
11256         mono_class_layout_fields (klass);
11257 }
11258
11259 static void
11260 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11261 {
11262         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11263         MonoReflectionPropertyBuilder *pb;
11264         MonoImage *image = klass->image;
11265         MonoProperty *properties;
11266         int i;
11267
11268         mono_error_init (error);
11269
11270         if (!klass->ext)
11271                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11272
11273         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11274         klass->ext->property.first = 0;
11275
11276         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11277         klass->ext->properties = properties;
11278         for (i = 0; i < klass->ext->property.count; ++i) {
11279                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11280                 properties [i].parent = klass;
11281                 properties [i].attrs = pb->attrs;
11282                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11283                 if (!mono_error_ok (error))
11284                         return;
11285                 if (pb->get_method)
11286                         properties [i].get = pb->get_method->mhandle;
11287                 if (pb->set_method)
11288                         properties [i].set = pb->set_method->mhandle;
11289
11290                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11291                 if (pb->def_value) {
11292                         guint32 len, idx;
11293                         const char *p, *p2;
11294                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11295                         if (!klass->ext->prop_def_values)
11296                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11297                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11298                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11299                         /* Copy the data from the blob since it might get realloc-ed */
11300                         p = assembly->blob.data + idx;
11301                         len = mono_metadata_decode_blob_size (p, &p2);
11302                         len += p2 - p;
11303                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11304                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11305                 }
11306         }
11307 }
11308
11309 MonoReflectionEvent *
11310 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11311 {
11312         MonoEvent *event = g_new0 (MonoEvent, 1);
11313         MonoClass *klass;
11314
11315         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11316
11317         event->parent = klass;
11318         event->attrs = eb->attrs;
11319         event->name = mono_string_to_utf8 (eb->name);
11320         if (eb->add_method)
11321                 event->add = eb->add_method->mhandle;
11322         if (eb->remove_method)
11323                 event->remove = eb->remove_method->mhandle;
11324         if (eb->raise_method)
11325                 event->raise = eb->raise_method->mhandle;
11326
11327 #ifndef MONO_SMALL_CONFIG
11328         if (eb->other_methods) {
11329                 int j;
11330                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11331                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11332                         MonoReflectionMethodBuilder *mb = 
11333                                 mono_array_get (eb->other_methods,
11334                                                 MonoReflectionMethodBuilder*, j);
11335                         event->other [j] = mb->mhandle;
11336                 }
11337         }
11338 #endif
11339
11340         return mono_event_get_object (mono_object_domain (tb), klass, event);
11341 }
11342
11343 static void
11344 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11345 {
11346         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11347         MonoReflectionEventBuilder *eb;
11348         MonoImage *image = klass->image;
11349         MonoEvent *events;
11350         int i;
11351
11352         mono_error_init (error);
11353
11354         if (!klass->ext)
11355                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11356
11357         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11358         klass->ext->event.first = 0;
11359
11360         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11361         klass->ext->events = events;
11362         for (i = 0; i < klass->ext->event.count; ++i) {
11363                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11364                 events [i].parent = klass;
11365                 events [i].attrs = eb->attrs;
11366                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11367                 if (!mono_error_ok (error))
11368                         return;
11369                 if (eb->add_method)
11370                         events [i].add = eb->add_method->mhandle;
11371                 if (eb->remove_method)
11372                         events [i].remove = eb->remove_method->mhandle;
11373                 if (eb->raise_method)
11374                         events [i].raise = eb->raise_method->mhandle;
11375
11376 #ifndef MONO_SMALL_CONFIG
11377                 if (eb->other_methods) {
11378                         int j;
11379                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11380                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11381                                 MonoReflectionMethodBuilder *mb = 
11382                                         mono_array_get (eb->other_methods,
11383                                                                         MonoReflectionMethodBuilder*, j);
11384                                 events [i].other [j] = mb->mhandle;
11385                         }
11386                 }
11387 #endif
11388                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11389         }
11390 }
11391
11392 static gboolean
11393 remove_instantiations_of_and_ensure_contents (gpointer key,
11394                                                   gpointer value,
11395                                                   gpointer user_data)
11396 {
11397         MonoType *type = (MonoType*)key;
11398         MonoClass *klass = (MonoClass*)user_data;
11399
11400         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11401                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11402                 return TRUE;
11403         } else
11404                 return FALSE;
11405 }
11406
11407 static void
11408 check_array_for_usertypes (MonoArray *arr)
11409 {
11410         int i;
11411
11412         if (!arr)
11413                 return;
11414
11415         for (i = 0; i < mono_array_length (arr); ++i)
11416                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11417 }
11418
11419 MonoReflectionType*
11420 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11421 {
11422         MonoError error;
11423         MonoClass *klass;
11424         MonoDomain* domain;
11425         MonoReflectionType* res;
11426         int i, j;
11427
11428         MONO_ARCH_SAVE_REGS;
11429
11430         domain = mono_object_domain (tb);
11431         klass = mono_class_from_mono_type (tb->type.type);
11432
11433         /*
11434          * Check for user defined Type subclasses.
11435          */
11436         RESOLVE_TYPE (tb->parent);
11437         check_array_for_usertypes (tb->interfaces);
11438         if (tb->fields) {
11439                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11440                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11441                         if (fb) {
11442                                 RESOLVE_TYPE (fb->type);
11443                                 check_array_for_usertypes (fb->modreq);
11444                                 check_array_for_usertypes (fb->modopt);
11445                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11446                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11447                         }
11448                 }
11449         }
11450         if (tb->methods) {
11451                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11452                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11453                         if (mb) {
11454                                 RESOLVE_TYPE (mb->rtype);
11455                                 check_array_for_usertypes (mb->return_modreq);
11456                                 check_array_for_usertypes (mb->return_modopt);
11457                                 check_array_for_usertypes (mb->parameters);
11458                                 if (mb->param_modreq)
11459                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11460                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11461                                 if (mb->param_modopt)
11462                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11463                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11464                         }
11465                 }
11466         }
11467         if (tb->ctors) {
11468                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11469                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11470                         if (mb) {
11471                                 check_array_for_usertypes (mb->parameters);
11472                                 if (mb->param_modreq)
11473                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11474                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11475                                 if (mb->param_modopt)
11476                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11477                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11478                         }
11479                 }
11480         }
11481
11482         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11483
11484         /* 
11485          * we need to lock the domain because the lock will be taken inside
11486          * So, we need to keep the locking order correct.
11487          */
11488         mono_loader_lock ();
11489         mono_domain_lock (domain);
11490         if (klass->wastypebuilder) {
11491                 mono_domain_unlock (domain);
11492                 mono_loader_unlock ();
11493                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11494         }
11495         /*
11496          * Fields to set in klass:
11497          * the various flags: delegate/unicode/contextbound etc.
11498          */
11499         klass->flags = tb->attrs;
11500         klass->has_cctor = 1;
11501         klass->has_finalize = 1;
11502         klass->has_finalize_inited = 1;
11503
11504         mono_class_setup_parent (klass, klass->parent);
11505         /* fool mono_class_setup_supertypes */
11506         klass->supertypes = NULL;
11507         mono_class_setup_supertypes (klass);
11508         mono_class_setup_mono_type (klass);
11509
11510 #if 0
11511         if (!((MonoDynamicImage*)klass->image)->run) {
11512                 if (klass->generic_container) {
11513                         /* FIXME: The code below can't handle generic classes */
11514                         klass->wastypebuilder = TRUE;
11515                         mono_loader_unlock ();
11516                         mono_domain_unlock (domain);
11517                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11518                 }
11519         }
11520 #endif
11521
11522         /* enums are done right away */
11523         if (!klass->enumtype)
11524                 ensure_runtime_vtable (klass);
11525
11526         if (tb->subtypes) {
11527                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11528                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11529                         mono_class_alloc_ext (klass);
11530                         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)));
11531                 }
11532         }
11533
11534         klass->nested_classes_inited = TRUE;
11535
11536         /* fields and object layout */
11537         if (klass->parent) {
11538                 if (!klass->parent->size_inited)
11539                         mono_class_init (klass->parent);
11540                 klass->instance_size = klass->parent->instance_size;
11541                 klass->sizes.class_size = 0;
11542                 klass->min_align = klass->parent->min_align;
11543                 /* if the type has no fields we won't call the field_setup
11544                  * routine which sets up klass->has_references.
11545                  */
11546                 klass->has_references |= klass->parent->has_references;
11547         } else {
11548                 klass->instance_size = sizeof (MonoObject);
11549                 klass->min_align = 1;
11550         }
11551
11552         /* FIXME: handle packing_size and instance_size */
11553         typebuilder_setup_fields (klass, &error);
11554         if (!mono_error_ok (&error))
11555                 goto failure;
11556         typebuilder_setup_properties (klass, &error);
11557         if (!mono_error_ok (&error))
11558                 goto failure;
11559
11560         typebuilder_setup_events (klass, &error);
11561         if (!mono_error_ok (&error))
11562                 goto failure;
11563
11564         klass->wastypebuilder = TRUE;
11565
11566         /* 
11567          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11568          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11569          * we want to return normal System.MonoType objects, so clear these out from the cache.
11570          *
11571          * Together with this we must ensure the contents of all instances to match the created type.
11572          */
11573         if (domain->type_hash && klass->generic_container)
11574                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11575
11576         mono_domain_unlock (domain);
11577         mono_loader_unlock ();
11578
11579         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11580                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11581                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11582         }
11583
11584         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11585         g_assert (res != (MonoReflectionType*)tb);
11586
11587         return res;
11588
11589 failure:
11590         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11591         klass->wastypebuilder = TRUE;
11592         mono_domain_unlock (domain);
11593         mono_loader_unlock ();
11594         mono_error_raise_exception (&error);
11595         return NULL;
11596 }
11597
11598 void
11599 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11600 {
11601         MonoGenericParamFull *param;
11602         MonoImage *image;
11603         MonoClass *pklass;
11604         MonoError error;
11605
11606         MONO_ARCH_SAVE_REGS;
11607
11608         image = &gparam->tbuilder->module->dynamic_image->image;
11609
11610         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11611
11612         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11613         g_assert (mono_error_ok (&error));
11614         param->param.num = gparam->index;
11615
11616         if (gparam->mbuilder) {
11617                 if (!gparam->mbuilder->generic_container) {
11618                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11619                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11620                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11621                         gparam->mbuilder->generic_container->is_method = TRUE;
11622                         /* 
11623                          * Cannot set owner.method, since the MonoMethod is not created yet.
11624                          * Set the image field instead, so type_in_image () works.
11625                          */
11626                         gparam->mbuilder->generic_container->image = klass->image;
11627                 }
11628                 param->param.owner = gparam->mbuilder->generic_container;
11629         } else if (gparam->tbuilder) {
11630                 if (!gparam->tbuilder->generic_container) {
11631                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11632                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11633                         gparam->tbuilder->generic_container->owner.klass = klass;
11634                 }
11635                 param->param.owner = gparam->tbuilder->generic_container;
11636         }
11637
11638         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11639
11640         gparam->type.type = &pklass->byval_arg;
11641
11642         mono_class_set_ref_info (pklass, gparam);
11643         mono_image_append_class_to_reflection_info_set (pklass);
11644 }
11645
11646 MonoArray *
11647 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11648 {
11649         MonoReflectionModuleBuilder *module = sig->module;
11650         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11651         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11652         guint32 buflen, i;
11653         MonoArray *result;
11654         SigBuffer buf;
11655
11656         check_array_for_usertypes (sig->arguments);
11657
11658         sigbuffer_init (&buf, 32);
11659
11660         sigbuffer_add_value (&buf, 0x07);
11661         sigbuffer_add_value (&buf, na);
11662         if (assembly != NULL){
11663                 for (i = 0; i < na; ++i) {
11664                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11665                         encode_reflection_type (assembly, type, &buf);
11666                 }
11667         }
11668
11669         buflen = buf.p - buf.buf;
11670         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11671         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11672         sigbuffer_free (&buf);
11673
11674         return result;
11675 }
11676
11677 MonoArray *
11678 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11679 {
11680         MonoDynamicImage *assembly = sig->module->dynamic_image;
11681         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11682         guint32 buflen, i;
11683         MonoArray *result;
11684         SigBuffer buf;
11685
11686         check_array_for_usertypes (sig->arguments);
11687
11688         sigbuffer_init (&buf, 32);
11689
11690         sigbuffer_add_value (&buf, 0x06);
11691         for (i = 0; i < na; ++i) {
11692                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11693                 encode_reflection_type (assembly, type, &buf);
11694         }
11695
11696         buflen = buf.p - buf.buf;
11697         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11698         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11699         sigbuffer_free (&buf);
11700
11701         return result;
11702 }
11703
11704 typedef struct {
11705         MonoMethod *handle;
11706         MonoDomain *domain;
11707 } DynamicMethodReleaseData;
11708
11709 /*
11710  * The runtime automatically clean up those after finalization.
11711 */      
11712 static MonoReferenceQueue *dynamic_method_queue;
11713
11714 static void
11715 free_dynamic_method (void *dynamic_method)
11716 {
11717         DynamicMethodReleaseData *data = dynamic_method;
11718
11719         mono_runtime_free_method (data->domain, data->handle);
11720         g_free (data);
11721 }
11722
11723 void 
11724 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11725 {
11726         MonoReferenceQueue *queue;
11727         MonoMethod *handle;
11728         DynamicMethodReleaseData *release_data;
11729         ReflectionMethodBuilder rmb;
11730         MonoMethodSignature *sig;
11731         MonoClass *klass;
11732         GSList *l;
11733         int i;
11734
11735         if (mono_runtime_is_shutting_down ())
11736                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11737
11738         if (!(queue = dynamic_method_queue)) {
11739                 mono_loader_lock ();
11740                 if (!(queue = dynamic_method_queue))
11741                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11742                 mono_loader_unlock ();
11743         }
11744
11745         sig = dynamic_method_to_signature (mb);
11746
11747         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11748
11749         /*
11750          * Resolve references.
11751          */
11752         /* 
11753          * Every second entry in the refs array is reserved for storing handle_class,
11754          * which is needed by the ldtoken implementation in the JIT.
11755          */
11756         rmb.nrefs = mb->nrefs;
11757         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11758         for (i = 0; i < mb->nrefs; i += 2) {
11759                 MonoClass *handle_class;
11760                 gpointer ref;
11761                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11762
11763                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11764                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11765                         /*
11766                          * The referenced DynamicMethod should already be created by the managed
11767                          * code, except in the case of circular references. In that case, we store
11768                          * method in the refs array, and fix it up later when the referenced 
11769                          * DynamicMethod is created.
11770                          */
11771                         if (method->mhandle) {
11772                                 ref = method->mhandle;
11773                         } else {
11774                                 /* FIXME: GC object stored in unmanaged memory */
11775                                 ref = method;
11776
11777                                 /* FIXME: GC object stored in unmanaged memory */
11778                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11779                         }
11780                         handle_class = mono_defaults.methodhandle_class;
11781                 } else {
11782                         MonoException *ex = NULL;
11783                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11784                         if (!ref)
11785                                 ex = mono_get_exception_type_load (NULL, NULL);
11786                         else if (mono_security_core_clr_enabled ())
11787                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11788
11789                         if (ex) {
11790                                 g_free (rmb.refs);
11791                                 mono_raise_exception (ex);
11792                                 return;
11793                         }
11794                 }
11795
11796                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11797                 rmb.refs [i + 1] = handle_class;
11798         }               
11799
11800         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11801
11802         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11803         release_data = g_new (DynamicMethodReleaseData, 1);
11804         release_data->handle = handle;
11805         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11806         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11807                 g_free (release_data);
11808
11809         /* Fix up refs entries pointing at us */
11810         for (l = mb->referenced_by; l; l = l->next) {
11811                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11812                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11813                 gpointer *data;
11814                 
11815                 g_assert (method->mhandle);
11816
11817                 data = (gpointer*)wrapper->method_data;
11818                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11819                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11820                                 data [i + 1] = mb->mhandle;
11821                 }
11822         }
11823         g_slist_free (mb->referenced_by);
11824
11825         g_free (rmb.refs);
11826
11827         /* ilgen is no longer needed */
11828         mb->ilgen = NULL;
11829 }
11830
11831 #endif /* DISABLE_REFLECTION_EMIT */
11832
11833 /**
11834  * 
11835  * mono_reflection_is_valid_dynamic_token:
11836  * 
11837  * Returns TRUE if token is valid.
11838  * 
11839  */
11840 gboolean
11841 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11842 {
11843         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11844 }
11845
11846 MonoMethodSignature *
11847 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11848 {
11849         MonoMethodSignature *sig;
11850         g_assert (image_is_dynamic (image));
11851
11852         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11853         if (sig)
11854                 return sig;
11855
11856         return mono_method_signature (method);
11857 }
11858
11859 #ifndef DISABLE_REFLECTION_EMIT
11860
11861 /**
11862  * mono_reflection_lookup_dynamic_token:
11863  *
11864  * Finish the Builder object pointed to by TOKEN and return the corresponding
11865  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11866  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11867  * mapping table.
11868  *
11869  * LOCKING: Take the loader lock
11870  */
11871 gpointer
11872 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11873 {
11874         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11875         MonoObject *obj;
11876         MonoClass *klass;
11877
11878         mono_loader_lock ();
11879         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11880         mono_loader_unlock ();
11881         if (!obj) {
11882                 if (valid_token)
11883                         g_error ("Could not find required dynamic token 0x%08x", token);
11884                 else
11885                         return NULL;
11886         }
11887
11888         if (!handle_class)
11889                 handle_class = &klass;
11890         return resolve_object (image, obj, handle_class, context);
11891 }
11892
11893 /*
11894  * ensure_complete_type:
11895  *
11896  *   Ensure that KLASS is completed if it is a dynamic type, or references
11897  * dynamic types.
11898  */
11899 static void
11900 ensure_complete_type (MonoClass *klass)
11901 {
11902         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11903                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11904
11905                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11906
11907                 // Asserting here could break a lot of code
11908                 //g_assert (klass->wastypebuilder);
11909         }
11910
11911         if (klass->generic_class) {
11912                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11913                 int i;
11914
11915                 for (i = 0; i < inst->type_argc; ++i) {
11916                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11917                 }
11918         }
11919 }
11920
11921 static gpointer
11922 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11923 {
11924         gpointer result = NULL;
11925
11926         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11927                 result = mono_string_intern ((MonoString*)obj);
11928                 *handle_class = mono_defaults.string_class;
11929                 g_assert (result);
11930         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11931                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11932                 MonoClass *mc = mono_class_from_mono_type (type);
11933                 if (!mono_class_init (mc))
11934                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11935
11936                 if (context) {
11937                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11938                         result = mono_class_from_mono_type (inflated);
11939                         mono_metadata_free_type (inflated);
11940                 } else {
11941                         result = mono_class_from_mono_type (type);
11942                 }
11943                 *handle_class = mono_defaults.typehandle_class;
11944                 g_assert (result);
11945         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11946                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11947                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11948                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11949                 result = ((MonoReflectionMethod*)obj)->method;
11950                 if (context)
11951                         result = mono_class_inflate_generic_method (result, context);
11952                 *handle_class = mono_defaults.methodhandle_class;
11953                 g_assert (result);
11954         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11955                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11956                 result = mb->mhandle;
11957                 if (!result) {
11958                         /* Type is not yet created */
11959                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11960
11961                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11962
11963                         /*
11964                          * Hopefully this has been filled in by calling CreateType() on the
11965                          * TypeBuilder.
11966                          */
11967                         /*
11968                          * TODO: This won't work if the application finishes another 
11969                          * TypeBuilder instance instead of this one.
11970                          */
11971                         result = mb->mhandle;
11972                 }
11973                 if (context)
11974                         result = mono_class_inflate_generic_method (result, context);
11975                 *handle_class = mono_defaults.methodhandle_class;
11976         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11977                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11978
11979                 result = cb->mhandle;
11980                 if (!result) {
11981                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11982
11983                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11984                         result = cb->mhandle;
11985                 }
11986                 if (context)
11987                         result = mono_class_inflate_generic_method (result, context);
11988                 *handle_class = mono_defaults.methodhandle_class;
11989         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11990                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11991
11992                 ensure_complete_type (field->parent);
11993                 if (context) {
11994                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11995                         MonoClass *class = mono_class_from_mono_type (inflated);
11996                         MonoClassField *inflated_field;
11997                         gpointer iter = NULL;
11998                         mono_metadata_free_type (inflated);
11999                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
12000                                 if (!strcmp (field->name, inflated_field->name))
12001                                         break;
12002                         }
12003                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12004                         result = inflated_field;
12005                 } else {
12006                         result = field;
12007                 }
12008                 *handle_class = mono_defaults.fieldhandle_class;
12009                 g_assert (result);
12010         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12011                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12012                 result = fb->handle;
12013
12014                 if (!result) {
12015                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12016
12017                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12018                         result = fb->handle;
12019                 }
12020
12021                 if (fb->handle && fb->handle->parent->generic_container) {
12022                         MonoClass *klass = fb->handle->parent;
12023                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12024                         MonoClass *inflated = mono_class_from_mono_type (type);
12025
12026                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12027                         g_assert (result);
12028                         mono_metadata_free_type (type);
12029                 }
12030                 *handle_class = mono_defaults.fieldhandle_class;
12031         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12032                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12033                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12034                 MonoClass *klass;
12035
12036                 klass = type->data.klass;
12037                 if (klass->wastypebuilder) {
12038                         /* Already created */
12039                         result = klass;
12040                 }
12041                 else {
12042                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12043                         result = type->data.klass;
12044                         g_assert (result);
12045                 }
12046                 *handle_class = mono_defaults.typehandle_class;
12047         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12048                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12049                 MonoMethodSignature *sig;
12050                 int nargs, i;
12051
12052                 if (helper->arguments)
12053                         nargs = mono_array_length (helper->arguments);
12054                 else
12055                         nargs = 0;
12056
12057                 sig = mono_metadata_signature_alloc (image, nargs);
12058                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12059                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12060
12061                 if (helper->unmanaged_call_conv) { /* unmanaged */
12062                         sig->call_convention = helper->unmanaged_call_conv - 1;
12063                         sig->pinvoke = TRUE;
12064                 } else if (helper->call_conv & 0x02) {
12065                         sig->call_convention = MONO_CALL_VARARG;
12066                 } else {
12067                         sig->call_convention = MONO_CALL_DEFAULT;
12068                 }
12069
12070                 sig->param_count = nargs;
12071                 /* TODO: Copy type ? */
12072                 sig->ret = helper->return_type->type;
12073                 for (i = 0; i < nargs; ++i)
12074                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12075
12076                 result = sig;
12077                 *handle_class = NULL;
12078         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12079                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12080                 /* Already created by the managed code */
12081                 g_assert (method->mhandle);
12082                 result = method->mhandle;
12083                 *handle_class = mono_defaults.methodhandle_class;
12084         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12085                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12086                 type = mono_class_inflate_generic_type (type, context);
12087                 result = mono_class_from_mono_type (type);
12088                 *handle_class = mono_defaults.typehandle_class;
12089                 g_assert (result);
12090                 mono_metadata_free_type (type);
12091         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12092                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12093                 type = mono_class_inflate_generic_type (type, context);
12094                 result = mono_class_from_mono_type (type);
12095                 *handle_class = mono_defaults.typehandle_class;
12096                 g_assert (result);
12097                 mono_metadata_free_type (type);
12098         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12099                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12100                 MonoClass *inflated;
12101                 MonoType *type;
12102                 MonoClassField *field;
12103
12104                 if (is_sre_field_builder (mono_object_class (f->fb)))
12105                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12106                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12107                         field = ((MonoReflectionField*)f->fb)->field;
12108                 else
12109                         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)));
12110
12111                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12112                 inflated = mono_class_from_mono_type (type);
12113
12114                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12115                 ensure_complete_type (field->parent);
12116                 g_assert (result);
12117                 mono_metadata_free_type (type);
12118                 *handle_class = mono_defaults.fieldhandle_class;
12119         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12120                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12121                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12122                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12123                 MonoMethod *method;
12124
12125                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12126                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12127                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12128                         method = ((MonoReflectionMethod *)c->cb)->method;
12129                 else
12130                         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)));
12131
12132                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12133                 *handle_class = mono_defaults.methodhandle_class;
12134                 mono_metadata_free_type (type);
12135         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12136                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12137                 if (m->method_args) {
12138                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12139                         if (context)
12140                                 result = mono_class_inflate_generic_method (result, context);
12141                 } else {
12142                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12143                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12144                         MonoMethod *method;
12145
12146                         if (is_sre_method_builder (mono_object_class (m->mb)))
12147                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12148                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12149                                 method = ((MonoReflectionMethod *)m->mb)->method;
12150                         else
12151                                 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)));
12152
12153                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12154                         mono_metadata_free_type (type);
12155                 }
12156                 *handle_class = mono_defaults.methodhandle_class;
12157         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12158                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12159                 MonoType *mtype;
12160                 MonoClass *klass;
12161                 MonoMethod *method;
12162                 gpointer iter;
12163                 char *name;
12164
12165                 mtype = mono_reflection_type_get_handle (m->parent);
12166                 klass = mono_class_from_mono_type (mtype);
12167
12168                 /* Find the method */
12169
12170                 name = mono_string_to_utf8 (m->name);
12171                 iter = NULL;
12172                 while ((method = mono_class_get_methods (klass, &iter))) {
12173                         if (!strcmp (method->name, name))
12174                                 break;
12175                 }
12176                 g_free (name);
12177
12178                 // FIXME:
12179                 g_assert (method);
12180                 // FIXME: Check parameters/return value etc. match
12181
12182                 result = method;
12183                 *handle_class = mono_defaults.methodhandle_class;
12184         } else if (is_sre_array (mono_object_get_class(obj)) ||
12185                                 is_sre_byref (mono_object_get_class(obj)) ||
12186                                 is_sre_pointer (mono_object_get_class(obj))) {
12187                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12188                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12189
12190                 if (context) {
12191                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12192                         result = mono_class_from_mono_type (inflated);
12193                         mono_metadata_free_type (inflated);
12194                 } else {
12195                         result = mono_class_from_mono_type (type);
12196                 }
12197                 *handle_class = mono_defaults.typehandle_class;
12198         } else {
12199                 g_print ("%s\n", obj->vtable->klass->name);
12200                 g_assert_not_reached ();
12201         }
12202         return result;
12203 }
12204
12205 #else /* DISABLE_REFLECTION_EMIT */
12206
12207 MonoArray*
12208 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12209 {
12210         g_assert_not_reached ();
12211         return NULL;
12212 }
12213
12214 void
12215 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12216 {
12217         g_assert_not_reached ();
12218 }
12219
12220 void
12221 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12222 {
12223         g_assert_not_reached ();
12224 }
12225
12226 void
12227 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12228 {
12229         g_assert_not_reached ();
12230 }
12231
12232 void
12233 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12234 {
12235         g_assert_not_reached ();
12236 }
12237
12238 void
12239 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12240 {
12241         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12242 }
12243
12244 void
12245 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12246 {
12247         g_assert_not_reached ();
12248 }
12249
12250 void
12251 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12252 {
12253         g_assert_not_reached ();
12254 }
12255
12256 MonoReflectionModule *
12257 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12258 {
12259         g_assert_not_reached ();
12260         return NULL;
12261 }
12262
12263 guint32
12264 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12265 {
12266         g_assert_not_reached ();
12267         return 0;
12268 }
12269
12270 guint32
12271 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12272 {
12273         g_assert_not_reached ();
12274         return 0;
12275 }
12276
12277 guint32
12278 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12279                                                  gboolean create_open_instance, gboolean register_token)
12280 {
12281         g_assert_not_reached ();
12282         return 0;
12283 }
12284
12285 void
12286 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12287 {
12288 }
12289
12290 void
12291 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12292 {
12293         g_assert_not_reached ();
12294 }
12295
12296 void
12297 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12298 {
12299         *overrides = NULL;
12300         *num_overrides = 0;
12301 }
12302
12303 MonoReflectionEvent *
12304 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12305 {
12306         g_assert_not_reached ();
12307         return NULL;
12308 }
12309
12310 MonoReflectionType*
12311 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12312 {
12313         g_assert_not_reached ();
12314         return NULL;
12315 }
12316
12317 void
12318 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12319 {
12320         g_assert_not_reached ();
12321 }
12322
12323 MonoArray *
12324 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12325 {
12326         g_assert_not_reached ();
12327         return NULL;
12328 }
12329
12330 MonoArray *
12331 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12332 {
12333         g_assert_not_reached ();
12334         return NULL;
12335 }
12336
12337 void 
12338 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12339 {
12340 }
12341
12342 gpointer
12343 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12344 {
12345         return NULL;
12346 }
12347
12348 MonoType*
12349 mono_reflection_type_get_handle (MonoReflectionType* ref)
12350 {
12351         if (!ref)
12352                 return NULL;
12353         return ref->type;
12354 }
12355
12356 void
12357 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12358 {
12359         g_assert_not_reached ();
12360 }
12361
12362 #endif /* DISABLE_REFLECTION_EMIT */
12363
12364 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12365 const static guint32 declsec_flags_map[] = {
12366         0x00000000,                                     /* empty */
12367         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12368         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12369         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12370         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12371         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12372         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12373         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12374         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12375         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12376         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12377         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12378         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12379         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12380         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12381         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12382         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12383         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12384         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12385 };
12386
12387 /*
12388  * Returns flags that includes all available security action associated to the handle.
12389  * @token: metadata token (either for a class or a method)
12390  * @image: image where resides the metadata.
12391  */
12392 static guint32
12393 mono_declsec_get_flags (MonoImage *image, guint32 token)
12394 {
12395         int index = mono_metadata_declsec_from_index (image, token);
12396         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12397         guint32 result = 0;
12398         guint32 action;
12399         int i;
12400
12401         /* HasSecurity can be present for other, not specially encoded, attributes,
12402            e.g. SuppressUnmanagedCodeSecurityAttribute */
12403         if (index < 0)
12404                 return 0;
12405
12406         for (i = index; i < t->rows; i++) {
12407                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12408
12409                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12410                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12411                         break;
12412
12413                 action = cols [MONO_DECL_SECURITY_ACTION];
12414                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12415                         result |= declsec_flags_map [action];
12416                 } else {
12417                         g_assert_not_reached ();
12418                 }
12419         }
12420         return result;
12421 }
12422
12423 /*
12424  * Get the security actions (in the form of flags) associated with the specified method.
12425  *
12426  * @method: The method for which we want the declarative security flags.
12427  * Return the declarative security flags for the method (only).
12428  *
12429  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12430  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12431  */
12432 guint32
12433 mono_declsec_flags_from_method (MonoMethod *method)
12434 {
12435         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12436                 /* FIXME: No cache (for the moment) */
12437                 guint32 idx = mono_method_get_index (method);
12438                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12439                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12440                 return mono_declsec_get_flags (method->klass->image, idx);
12441         }
12442         return 0;
12443 }
12444
12445 /*
12446  * Get the security actions (in the form of flags) associated with the specified class.
12447  *
12448  * @klass: The class for which we want the declarative security flags.
12449  * Return the declarative security flags for the class.
12450  *
12451  * Note: We cache the flags inside the MonoClass structure as this will get 
12452  *       called very often (at least for each method).
12453  */
12454 guint32
12455 mono_declsec_flags_from_class (MonoClass *klass)
12456 {
12457         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12458                 if (!klass->ext || !klass->ext->declsec_flags) {
12459                         guint32 idx;
12460
12461                         idx = mono_metadata_token_index (klass->type_token);
12462                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12463                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12464                         mono_loader_lock ();
12465                         mono_class_alloc_ext (klass);
12466                         mono_loader_unlock ();
12467                         /* we cache the flags on classes */
12468                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12469                 }
12470                 return klass->ext->declsec_flags;
12471         }
12472         return 0;
12473 }
12474
12475 /*
12476  * Get the security actions (in the form of flags) associated with the specified assembly.
12477  *
12478  * @assembly: The assembly for which we want the declarative security flags.
12479  * Return the declarative security flags for the assembly.
12480  */
12481 guint32
12482 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12483 {
12484         guint32 idx = 1; /* there is only one assembly */
12485         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12486         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12487         return mono_declsec_get_flags (assembly->image, idx);
12488 }
12489
12490
12491 /*
12492  * Fill actions for the specific index (which may either be an encoded class token or
12493  * an encoded method token) from the metadata image.
12494  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12495  */
12496 static MonoBoolean
12497 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12498         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12499 {
12500         MonoBoolean result = FALSE;
12501         MonoTableInfo *t;
12502         guint32 cols [MONO_DECL_SECURITY_SIZE];
12503         int index = mono_metadata_declsec_from_index (image, token);
12504         int i;
12505
12506         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12507         for (i = index; i < t->rows; i++) {
12508                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12509
12510                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12511                         return result;
12512
12513                 /* if present only replace (class) permissions with method permissions */
12514                 /* if empty accept either class or method permissions */
12515                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12516                         if (!actions->demand.blob) {
12517                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12518                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12519                                 actions->demand.blob = (char*) (blob + 2);
12520                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12521                                 result = TRUE;
12522                         }
12523                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12524                         if (!actions->noncasdemand.blob) {
12525                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12526                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12527                                 actions->noncasdemand.blob = (char*) (blob + 2);
12528                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12529                                 result = TRUE;
12530                         }
12531                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12532                         if (!actions->demandchoice.blob) {
12533                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12534                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12535                                 actions->demandchoice.blob = (char*) (blob + 2);
12536                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12537                                 result = TRUE;
12538                         }
12539                 }
12540         }
12541
12542         return result;
12543 }
12544
12545 static MonoBoolean
12546 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12547         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12548 {
12549         guint32 idx = mono_metadata_token_index (klass->type_token);
12550         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12551         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12552         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12553 }
12554
12555 static MonoBoolean
12556 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12557         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12558 {
12559         guint32 idx = mono_method_get_index (method);
12560         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12561         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12562         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12563 }
12564
12565 /*
12566  * Collect all actions (that requires to generate code in mini) assigned for
12567  * the specified method.
12568  * Note: Don't use the content of actions if the function return FALSE.
12569  */
12570 MonoBoolean
12571 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12572 {
12573         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12574                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12575         MonoBoolean result = FALSE;
12576         guint32 flags;
12577
12578         /* quick exit if no declarative security is present in the metadata */
12579         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12580                 return FALSE;
12581
12582         /* we want the original as the wrapper is "free" of the security informations */
12583         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12584                 method = mono_marshal_method_from_wrapper (method);
12585                 if (!method)
12586                         return FALSE;
12587         }
12588
12589         /* First we look for method-level attributes */
12590         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12591                 mono_class_init (method->klass);
12592                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12593
12594                 result = mono_declsec_get_method_demands_params (method, demands, 
12595                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12596         }
12597
12598         /* Here we use (or create) the class declarative cache to look for demands */
12599         flags = mono_declsec_flags_from_class (method->klass);
12600         if (flags & mask) {
12601                 if (!result) {
12602                         mono_class_init (method->klass);
12603                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12604                 }
12605                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12606                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12607         }
12608
12609         /* The boolean return value is used as a shortcut in case nothing needs to
12610            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12611         return result;
12612 }
12613
12614
12615 /*
12616  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12617  *
12618  * Note: Don't use the content of actions if the function return FALSE.
12619  */
12620 MonoBoolean
12621 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12622 {
12623         MonoBoolean result = FALSE;
12624         guint32 flags;
12625
12626         /* quick exit if no declarative security is present in the metadata */
12627         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12628                 return FALSE;
12629
12630         /* we want the original as the wrapper is "free" of the security informations */
12631         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12632                 method = mono_marshal_method_from_wrapper (method);
12633                 if (!method)
12634                         return FALSE;
12635         }
12636
12637         /* results are independant - zeroize both */
12638         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12639         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12640
12641         /* First we look for method-level attributes */
12642         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12643                 mono_class_init (method->klass);
12644
12645                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12646                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12647         }
12648
12649         /* Here we use (or create) the class declarative cache to look for demands */
12650         flags = mono_declsec_flags_from_class (method->klass);
12651         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12652                 mono_class_init (method->klass);
12653
12654                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12655                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12656         }
12657
12658         return result;
12659 }
12660
12661 /*
12662  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12663  *
12664  * @klass       The inherited class - this is the class that provides the security check (attributes)
12665  * @demans      
12666  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12667  * 
12668  * Note: Don't use the content of actions if the function return FALSE.
12669  */
12670 MonoBoolean
12671 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12672 {
12673         MonoBoolean result = FALSE;
12674         guint32 flags;
12675
12676         /* quick exit if no declarative security is present in the metadata */
12677         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12678                 return FALSE;
12679
12680         /* Here we use (or create) the class declarative cache to look for demands */
12681         flags = mono_declsec_flags_from_class (klass);
12682         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12683                 mono_class_init (klass);
12684                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12685
12686                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12687                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12688         }
12689
12690         return result;
12691 }
12692
12693 /*
12694  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12695  *
12696  * Note: Don't use the content of actions if the function return FALSE.
12697  */
12698 MonoBoolean
12699 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12700 {
12701         /* quick exit if no declarative security is present in the metadata */
12702         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12703                 return FALSE;
12704
12705         /* we want the original as the wrapper is "free" of the security informations */
12706         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12707                 method = mono_marshal_method_from_wrapper (method);
12708                 if (!method)
12709                         return FALSE;
12710         }
12711
12712         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12713                 mono_class_init (method->klass);
12714                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12715
12716                 return mono_declsec_get_method_demands_params (method, demands, 
12717                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12718         }
12719         return FALSE;
12720 }
12721
12722
12723 static MonoBoolean
12724 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12725 {
12726         guint32 cols [MONO_DECL_SECURITY_SIZE];
12727         MonoTableInfo *t;
12728         int i;
12729
12730         int index = mono_metadata_declsec_from_index (image, token);
12731         if (index == -1)
12732                 return FALSE;
12733
12734         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12735         for (i = index; i < t->rows; i++) {
12736                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12737
12738                 /* shortcut - index are ordered */
12739                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12740                         return FALSE;
12741
12742                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12743                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12744                         entry->blob = (char*) (metadata + 2);
12745                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12746                         return TRUE;
12747                 }
12748         }
12749
12750         return FALSE;
12751 }
12752
12753 MonoBoolean
12754 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12755 {
12756         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12757                 guint32 idx = mono_method_get_index (method);
12758                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12759                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12760                 return get_declsec_action (method->klass->image, idx, action, entry);
12761         }
12762         return FALSE;
12763 }
12764
12765 MonoBoolean
12766 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12767 {
12768         /* use cache */
12769         guint32 flags = mono_declsec_flags_from_class (klass);
12770         if (declsec_flags_map [action] & flags) {
12771                 guint32 idx = mono_metadata_token_index (klass->type_token);
12772                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12773                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12774                 return get_declsec_action (klass->image, idx, action, entry);
12775         }
12776         return FALSE;
12777 }
12778
12779 MonoBoolean
12780 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12781 {
12782         guint32 idx = 1; /* there is only one assembly */
12783         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12784         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12785
12786         return get_declsec_action (assembly->image, idx, action, entry);
12787 }
12788
12789 gboolean
12790 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12791 {
12792         MonoObject *res, *exc;
12793         void *params [1];
12794         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12795         static MonoMethod *method = NULL;
12796
12797         if (!System_Reflection_Emit_TypeBuilder) {
12798                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12799                 g_assert (System_Reflection_Emit_TypeBuilder);
12800         }
12801         if (method == NULL) {
12802                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12803                 g_assert (method);
12804         }
12805
12806         /* 
12807          * The result of mono_type_get_object () might be a System.MonoType but we
12808          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12809          */
12810         g_assert (mono_class_get_ref_info (klass));
12811         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12812
12813         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12814
12815         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12816         if (exc)
12817                 return FALSE;
12818         else
12819                 return *(MonoBoolean*)mono_object_unbox (res);
12820 }
12821
12822 /**
12823  * mono_reflection_type_get_type:
12824  * @reftype: the System.Type object
12825  *
12826  * Returns the MonoType* associated with the C# System.Type object @reftype.
12827  */
12828 MonoType*
12829 mono_reflection_type_get_type (MonoReflectionType *reftype)
12830 {
12831         g_assert (reftype);
12832
12833         return mono_reflection_type_get_handle (reftype);
12834 }
12835
12836 /**
12837  * mono_reflection_assembly_get_assembly:
12838  * @refassembly: the System.Reflection.Assembly object
12839  *
12840  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
12841  */
12842 MonoAssembly*
12843 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
12844 {
12845         g_assert (refassembly);
12846
12847         return refassembly->assembly;
12848 }
12849