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