[reflection] Don't raise in mono_type_get_object_checked
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void    ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
224
225 static inline void
226 dynamic_images_lock (void)
227 {
228         mono_os_mutex_lock (&dynamic_images_mutex);
229 }
230
231 static inline void
232 dynamic_images_unlock (void)
233 {
234         mono_os_mutex_unlock (&dynamic_images_mutex);
235 }
236
237 /**
238  * mono_find_dynamic_image_owner:
239  *
240  * Find the dynamic image, if any, which a given pointer is located in the memory of.
241  */
242 MonoImage *
243 mono_find_dynamic_image_owner (void *ptr)
244 {
245         MonoImage *owner = NULL;
246         int i;
247
248         dynamic_images_lock ();
249
250         if (dynamic_images)
251         {
252                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254                         if (mono_mempool_contains_addr (image->mempool, ptr))
255                                 owner = image;
256                 }
257         }
258
259         dynamic_images_unlock ();
260
261         return owner;
262 }
263
264 void
265 mono_reflection_init (void)
266 {
267         mono_os_mutex_init (&dynamic_images_mutex);
268 }
269
270 static inline void
271 dynamic_image_lock (MonoDynamicImage *image)
272 {
273         MONO_PREPARE_BLOCKING;
274         mono_image_lock ((MonoImage*)image);
275         MONO_FINISH_BLOCKING;
276 }
277
278 static inline void
279 dynamic_image_unlock (MonoDynamicImage *image)
280 {
281         mono_image_unlock ((MonoImage*)image);
282 }
283
284 static void
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
286 {
287         MONO_REQ_GC_UNSAFE_MODE;
288
289         dynamic_image_lock (assembly);
290         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291         dynamic_image_unlock (assembly);
292 }
293
294 static MonoObject*
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
296 {
297         MONO_REQ_GC_UNSAFE_MODE;
298
299         MonoObject *obj;
300
301         dynamic_image_lock (assembly);
302         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303         dynamic_image_unlock (assembly);
304
305         return obj;
306 }
307
308 static void
309 sigbuffer_init (SigBuffer *buf, int size)
310 {
311         MONO_REQ_GC_NEUTRAL_MODE;
312
313         buf->buf = (char *)g_malloc (size);
314         buf->p = buf->buf;
315         buf->end = buf->buf + size;
316 }
317
318 static void
319 sigbuffer_make_room (SigBuffer *buf, int size)
320 {
321         MONO_REQ_GC_NEUTRAL_MODE;
322
323         if (buf->end - buf->p < size) {
324                 int new_size = buf->end - buf->buf + size + 32;
325                 char *p = (char *)g_realloc (buf->buf, new_size);
326                 size = buf->p - buf->buf;
327                 buf->buf = p;
328                 buf->p = p + size;
329                 buf->end = buf->buf + new_size;
330         }
331 }
332
333 static void
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
335 {
336         MONO_REQ_GC_NEUTRAL_MODE;
337
338         sigbuffer_make_room (buf, 6);
339         mono_metadata_encode_value (val, buf->p, &buf->p);
340 }
341
342 static void
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
344 {
345         MONO_REQ_GC_NEUTRAL_MODE;
346
347         sigbuffer_make_room (buf, 1);
348         buf->p [0] = val;
349         buf->p++;
350 }
351
352 static void
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
354 {
355         MONO_REQ_GC_NEUTRAL_MODE;
356
357         sigbuffer_make_room (buf, size);
358         memcpy (buf->p, p, size);
359         buf->p += size;
360 }
361
362 static void
363 sigbuffer_free (SigBuffer *buf)
364 {
365         MONO_REQ_GC_NEUTRAL_MODE;
366
367         g_free (buf->buf);
368 }
369
370 #ifndef DISABLE_REFLECTION_EMIT
371 /**
372  * mp_g_alloc:
373  *
374  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
375  * from the C heap.
376  */
377 static gpointer
378 image_g_malloc (MonoImage *image, guint size)
379 {
380         MONO_REQ_GC_NEUTRAL_MODE;
381
382         if (image)
383                 return mono_image_alloc (image, size);
384         else
385                 return g_malloc (size);
386 }
387 #endif /* !DISABLE_REFLECTION_EMIT */
388
389 /**
390  * image_g_alloc0:
391  *
392  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
393  * from the C heap.
394  */
395 static gpointer
396 image_g_malloc0 (MonoImage *image, guint size)
397 {
398         MONO_REQ_GC_NEUTRAL_MODE;
399
400         if (image)
401                 return mono_image_alloc0 (image, size);
402         else
403                 return g_malloc0 (size);
404 }
405
406 #ifndef DISABLE_REFLECTION_EMIT
407 static char*
408 image_strdup (MonoImage *image, const char *s)
409 {
410         MONO_REQ_GC_NEUTRAL_MODE;
411
412         if (image)
413                 return mono_image_strdup (image, s);
414         else
415                 return g_strdup (s);
416 }
417 #endif
418
419 #define image_g_new(image,struct_type, n_structs)               \
420     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
421
422 #define image_g_new0(image,struct_type, n_structs)              \
423     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
424
425
426 static void
427 alloc_table (MonoDynamicTable *table, guint nrows)
428 {
429         MONO_REQ_GC_NEUTRAL_MODE;
430
431         table->rows = nrows;
432         g_assert (table->columns);
433         if (nrows + 1 >= table->alloc_rows) {
434                 while (nrows + 1 >= table->alloc_rows) {
435                         if (table->alloc_rows == 0)
436                                 table->alloc_rows = 16;
437                         else
438                                 table->alloc_rows *= 2;
439                 }
440
441                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
442         }
443 }
444
445 static void
446 make_room_in_stream (MonoDynamicStream *stream, int size)
447 {
448         MONO_REQ_GC_NEUTRAL_MODE;
449
450         if (size <= stream->alloc_size)
451                 return;
452         
453         while (stream->alloc_size <= size) {
454                 if (stream->alloc_size < 4096)
455                         stream->alloc_size = 4096;
456                 else
457                         stream->alloc_size *= 2;
458         }
459         
460         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
461 }
462
463 static guint32
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
465 {
466         MONO_REQ_GC_NEUTRAL_MODE;
467
468         guint32 idx;
469         guint32 len;
470         gpointer oldkey, oldval;
471
472         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473                 return GPOINTER_TO_UINT (oldval);
474
475         len = strlen (str) + 1;
476         idx = sh->index;
477         
478         make_room_in_stream (sh, idx + len);
479
480         /*
481          * We strdup the string even if we already copy them in sh->data
482          * so that the string pointers in the hash remain valid even if
483          * we need to realloc sh->data. We may want to avoid that later.
484          */
485         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486         memcpy (sh->data + idx, str, len);
487         sh->index += len;
488         return idx;
489 }
490
491 static guint32
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
493 {
494         MONO_REQ_GC_UNSAFE_MODE;
495
496         char *name = mono_string_to_utf8 (str);
497         guint32 idx;
498         idx = string_heap_insert (sh, name);
499         g_free (name);
500         return idx;
501 }
502
503 #ifndef DISABLE_REFLECTION_EMIT
504 static void
505 string_heap_init (MonoDynamicStream *sh)
506 {
507         MONO_REQ_GC_NEUTRAL_MODE;
508
509         sh->index = 0;
510         sh->alloc_size = 4096;
511         sh->data = (char *)g_malloc (4096);
512         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513         string_heap_insert (sh, "");
514 }
515 #endif
516
517 static guint32
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
519 {
520         MONO_REQ_GC_NEUTRAL_MODE;
521
522         guint32 idx;
523         
524         make_room_in_stream (stream, stream->index + len);
525         memcpy (stream->data + stream->index, data, len);
526         idx = stream->index;
527         stream->index += len;
528         /* 
529          * align index? Not without adding an additional param that controls it since
530          * we may store a blob value in pieces.
531          */
532         return idx;
533 }
534
535 static guint32
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
537 {
538         MONO_REQ_GC_NEUTRAL_MODE;
539
540         guint32 idx;
541         
542         make_room_in_stream (stream, stream->index + len);
543         memset (stream->data + stream->index, 0, len);
544         idx = stream->index;
545         stream->index += len;
546         return idx;
547 }
548
549 static void
550 stream_data_align (MonoDynamicStream *stream)
551 {
552         MONO_REQ_GC_NEUTRAL_MODE;
553
554         char buf [4] = {0};
555         guint32 count = stream->index % 4;
556
557         /* we assume the stream data will be aligned */
558         if (count)
559                 mono_image_add_stream_data (stream, buf, 4 - count);
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static int
564 mono_blob_entry_hash (const char* str)
565 {
566         MONO_REQ_GC_NEUTRAL_MODE;
567
568         guint len, h;
569         const char *end;
570         len = mono_metadata_decode_blob_size (str, &str);
571         if (len > 0) {
572                 end = str + len;
573                 h = *str;
574                 for (str += 1; str < end; str++)
575                         h = (h << 5) - h + *str;
576                 return h;
577         } else {
578                 return 0;
579         }
580 }
581
582 static gboolean
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584         MONO_REQ_GC_NEUTRAL_MODE;
585
586         int len, len2;
587         const char *end1;
588         const char *end2;
589         len = mono_metadata_decode_blob_size (str1, &end1);
590         len2 = mono_metadata_decode_blob_size (str2, &end2);
591         if (len != len2)
592                 return 0;
593         return memcmp (end1, end2, len) == 0;
594 }
595 #endif
596 static guint32
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
598 {
599         MONO_REQ_GC_NEUTRAL_MODE;
600
601         guint32 idx;
602         char *copy;
603         gpointer oldkey, oldval;
604
605         copy = (char *)g_malloc (s1+s2);
606         memcpy (copy, b1, s1);
607         memcpy (copy + s1, b2, s2);
608         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
609                 g_free (copy);
610                 idx = GPOINTER_TO_UINT (oldval);
611         } else {
612                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613                 mono_image_add_stream_data (&assembly->blob, b2, s2);
614                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
615         }
616         return idx;
617 }
618
619 static guint32
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
621 {
622         MONO_REQ_GC_NEUTRAL_MODE;
623
624         char blob_size [8];
625         char *b = blob_size;
626         guint32 size = buf->p - buf->buf;
627         /* store length */
628         g_assert (size <= (buf->end - buf->buf));
629         mono_metadata_encode_value (size, b, &b);
630         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
631 }
632
633 /*
634  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635  * dest may be misaligned.
636  */
637 static void
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639         MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
641         int elem;
642
643         for (elem = 0; elem < nelem; ++elem) {
644                 switch (len) {
645                 case 1:
646                         *dest = *val;
647                         break;
648                 case 2:
649                         dest [0] = val [1];
650                         dest [1] = val [0];
651                         break;
652                 case 4:
653                         dest [0] = val [3];
654                         dest [1] = val [2];
655                         dest [2] = val [1];
656                         dest [3] = val [0];
657                         break;
658                 case 8:
659                         dest [0] = val [7];
660                         dest [1] = val [6];
661                         dest [2] = val [5];
662                         dest [3] = val [4];
663                         dest [4] = val [3];
664                         dest [5] = val [2];
665                         dest [6] = val [1];
666                         dest [7] = val [0];
667                         break;
668                 default:
669                         g_assert_not_reached ();
670                 }
671                 dest += len;
672                 val += len;
673         }
674 #else
675         memcpy (dest, val, len * nelem);
676 #endif
677 }
678
679 static guint32
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
681 {
682         MONO_REQ_GC_UNSAFE_MODE;
683         
684         char blob_size [64];
685         char *b = blob_size;
686         guint32 idx = 0, len;
687
688         len = str->length * 2;
689         mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
691         {
692                 char *swapped = g_malloc (2 * mono_string_length (str));
693                 const char *p = (const char*)mono_string_chars (str);
694
695                 swap_with_size (swapped, p, 2, mono_string_length (str));
696                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
697                 g_free (swapped);
698         }
699 #else
700         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
701 #endif
702         return idx;
703 }
704
705 #ifndef DISABLE_REFLECTION_EMIT
706 static MonoClass *
707 default_class_from_mono_type (MonoType *type)
708 {
709         MONO_REQ_GC_NEUTRAL_MODE;
710
711         switch (type->type) {
712         case MONO_TYPE_OBJECT:
713                 return mono_defaults.object_class;
714         case MONO_TYPE_VOID:
715                 return mono_defaults.void_class;
716         case MONO_TYPE_BOOLEAN:
717                 return mono_defaults.boolean_class;
718         case MONO_TYPE_CHAR:
719                 return mono_defaults.char_class;
720         case MONO_TYPE_I1:
721                 return mono_defaults.sbyte_class;
722         case MONO_TYPE_U1:
723                 return mono_defaults.byte_class;
724         case MONO_TYPE_I2:
725                 return mono_defaults.int16_class;
726         case MONO_TYPE_U2:
727                 return mono_defaults.uint16_class;
728         case MONO_TYPE_I4:
729                 return mono_defaults.int32_class;
730         case MONO_TYPE_U4:
731                 return mono_defaults.uint32_class;
732         case MONO_TYPE_I:
733                 return mono_defaults.int_class;
734         case MONO_TYPE_U:
735                 return mono_defaults.uint_class;
736         case MONO_TYPE_I8:
737                 return mono_defaults.int64_class;
738         case MONO_TYPE_U8:
739                 return mono_defaults.uint64_class;
740         case MONO_TYPE_R4:
741                 return mono_defaults.single_class;
742         case MONO_TYPE_R8:
743                 return mono_defaults.double_class;
744         case MONO_TYPE_STRING:
745                 return mono_defaults.string_class;
746         default:
747                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748                 g_assert_not_reached ();
749         }
750         
751         return NULL;
752 }
753 #endif
754
755 /*
756  * mono_class_get_ref_info:
757  *
758  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
759  */
760 gpointer
761 mono_class_get_ref_info (MonoClass *klass)
762 {
763         MONO_REQ_GC_UNSAFE_MODE;
764
765         if (klass->ref_info_handle == 0)
766                 return NULL;
767         else
768                 return mono_gchandle_get_target (klass->ref_info_handle);
769 }
770
771 void
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
773 {
774         MONO_REQ_GC_UNSAFE_MODE;
775
776         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777         g_assert (klass->ref_info_handle != 0);
778 }
779
780 void
781 mono_class_free_ref_info (MonoClass *klass)
782 {
783         MONO_REQ_GC_NEUTRAL_MODE;
784
785         if (klass->ref_info_handle) {
786                 mono_gchandle_free (klass->ref_info_handle);
787                 klass->ref_info_handle = 0;
788         }
789 }
790
791 static void
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
793 {
794         MONO_REQ_GC_NEUTRAL_MODE;
795
796         int i;
797         MonoGenericInst *class_inst;
798         MonoClass *klass;
799
800         g_assert (gclass);
801
802         class_inst = gclass->context.class_inst;
803
804         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805         klass = gclass->container_class;
806         sigbuffer_add_value (buf, klass->byval_arg.type);
807         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
808
809         sigbuffer_add_value (buf, class_inst->type_argc);
810         for (i = 0; i < class_inst->type_argc; ++i)
811                 encode_type (assembly, class_inst->type_argv [i], buf);
812
813 }
814
815 static void
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (!type) {
821                 g_assert_not_reached ();
822                 return;
823         }
824                 
825         if (type->byref)
826                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
827
828         switch (type->type){
829         case MONO_TYPE_VOID:
830         case MONO_TYPE_BOOLEAN:
831         case MONO_TYPE_CHAR:
832         case MONO_TYPE_I1:
833         case MONO_TYPE_U1:
834         case MONO_TYPE_I2:
835         case MONO_TYPE_U2:
836         case MONO_TYPE_I4:
837         case MONO_TYPE_U4:
838         case MONO_TYPE_I8:
839         case MONO_TYPE_U8:
840         case MONO_TYPE_R4:
841         case MONO_TYPE_R8:
842         case MONO_TYPE_I:
843         case MONO_TYPE_U:
844         case MONO_TYPE_STRING:
845         case MONO_TYPE_OBJECT:
846         case MONO_TYPE_TYPEDBYREF:
847                 sigbuffer_add_value (buf, type->type);
848                 break;
849         case MONO_TYPE_PTR:
850                 sigbuffer_add_value (buf, type->type);
851                 encode_type (assembly, type->data.type, buf);
852                 break;
853         case MONO_TYPE_SZARRAY:
854                 sigbuffer_add_value (buf, type->type);
855                 encode_type (assembly, &type->data.klass->byval_arg, buf);
856                 break;
857         case MONO_TYPE_VALUETYPE:
858         case MONO_TYPE_CLASS: {
859                 MonoClass *k = mono_class_from_mono_type (type);
860
861                 if (k->generic_container) {
862                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863                         encode_generic_class (assembly, gclass, buf);
864                 } else {
865                         /*
866                          * Make sure we use the correct type.
867                          */
868                         sigbuffer_add_value (buf, k->byval_arg.type);
869                         /*
870                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871                          * otherwise two typerefs could point to the same type, leading to
872                          * verification errors.
873                          */
874                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
875                 }
876                 break;
877         }
878         case MONO_TYPE_ARRAY:
879                 sigbuffer_add_value (buf, type->type);
880                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881                 sigbuffer_add_value (buf, type->data.array->rank);
882                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883                 sigbuffer_add_value (buf, 0);
884                 break;
885         case MONO_TYPE_GENERICINST:
886                 encode_generic_class (assembly, type->data.generic_class, buf);
887                 break;
888         case MONO_TYPE_VAR:
889         case MONO_TYPE_MVAR:
890                 sigbuffer_add_value (buf, type->type);
891                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
892                 break;
893         default:
894                 g_error ("need to encode type %x", type->type);
895         }
896 }
897
898 static void
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
900 {
901         MONO_REQ_GC_UNSAFE_MODE;
902
903         if (!type) {
904                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
905                 return;
906         }
907
908         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
909 }
910
911 static void
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
913 {
914         MONO_REQ_GC_UNSAFE_MODE;
915
916         int i;
917
918         if (modreq) {
919                 for (i = 0; i < mono_array_length (modreq); ++i) {
920                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
923                 }
924         }
925         if (modopt) {
926                 for (i = 0; i < mono_array_length (modopt); ++i) {
927                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
930                 }
931         }
932 }
933
934 #ifndef DISABLE_REFLECTION_EMIT
935 static guint32
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
937 {
938         MONO_REQ_GC_UNSAFE_MODE;
939
940         SigBuffer buf;
941         int i;
942         guint32 nparams =  sig->param_count;
943         guint32 idx;
944
945         if (!assembly->save)
946                 return 0;
947
948         sigbuffer_init (&buf, 32);
949         /*
950          * FIXME: vararg, explicit_this, differenc call_conv values...
951          */
952         idx = sig->call_convention;
953         if (sig->hasthis)
954                 idx |= 0x20; /* hasthis */
955         if (sig->generic_param_count)
956                 idx |= 0x10; /* generic */
957         sigbuffer_add_byte (&buf, idx);
958         if (sig->generic_param_count)
959                 sigbuffer_add_value (&buf, sig->generic_param_count);
960         sigbuffer_add_value (&buf, nparams);
961         encode_type (assembly, sig->ret, &buf);
962         for (i = 0; i < nparams; ++i) {
963                 if (i == sig->sentinelpos)
964                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965                 encode_type (assembly, sig->params [i], &buf);
966         }
967         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968         sigbuffer_free (&buf);
969         return idx;
970 }
971 #endif
972
973 static guint32
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
975 {
976         MONO_REQ_GC_UNSAFE_MODE;
977
978         /*
979          * FIXME: reuse code from method_encode_signature().
980          */
981         SigBuffer buf;
982         int i;
983         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
984         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
986         guint32 idx;
987
988         sigbuffer_init (&buf, 32);
989         /* LAMESPEC: all the call conv spec is foobared */
990         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991         if (mb->call_conv & 2)
992                 idx |= 0x5; /* vararg */
993         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994                 idx |= 0x20; /* hasthis */
995         if (ngparams)
996                 idx |= 0x10; /* generic */
997         sigbuffer_add_byte (&buf, idx);
998         if (ngparams)
999                 sigbuffer_add_value (&buf, ngparams);
1000         sigbuffer_add_value (&buf, nparams + notypes);
1001         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002         encode_reflection_type (assembly, mb->rtype, &buf);
1003         for (i = 0; i < nparams; ++i) {
1004                 MonoArray *modreq = NULL;
1005                 MonoArray *modopt = NULL;
1006                 MonoReflectionType *pt;
1007
1008                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014                 encode_reflection_type (assembly, pt, &buf);
1015         }
1016         if (notypes)
1017                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018         for (i = 0; i < notypes; ++i) {
1019                 MonoReflectionType *pt;
1020
1021                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022                 encode_reflection_type (assembly, pt, &buf);
1023         }
1024
1025         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026         sigbuffer_free (&buf);
1027         return idx;
1028 }
1029
1030 static guint32
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1032 {
1033         MONO_REQ_GC_UNSAFE_MODE;
1034
1035         MonoDynamicTable *table;
1036         guint32 *values;
1037         guint32 idx, sig_idx;
1038         guint nl = mono_array_length (ilgen->locals);
1039         SigBuffer buf;
1040         int i;
1041
1042         sigbuffer_init (&buf, 32);
1043         sigbuffer_add_value (&buf, 0x07);
1044         sigbuffer_add_value (&buf, nl);
1045         for (i = 0; i < nl; ++i) {
1046                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1047                 
1048                 if (lb->is_pinned)
1049                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1050                 
1051                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1052         }
1053         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054         sigbuffer_free (&buf);
1055
1056         if (assembly->standalonesig_cache == NULL)
1057                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1059         if (idx)
1060                 return idx;
1061
1062         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063         idx = table->next_idx ++;
1064         table->rows ++;
1065         alloc_table (table, table->rows);
1066         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1067
1068         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1069
1070         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1071
1072         return idx;
1073 }
1074
1075 static guint32
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1077 {
1078         MONO_REQ_GC_UNSAFE_MODE;
1079
1080         guint32 num_clauses = 0;
1081         int i;
1082
1083         MonoILExceptionInfo *ex_info;
1084         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086                 if (ex_info->handlers)
1087                         num_clauses += mono_array_length (ex_info->handlers);
1088                 else
1089                         num_clauses++;
1090         }
1091
1092         return num_clauses;
1093 }
1094
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1098 {
1099         MONO_REQ_GC_UNSAFE_MODE;
1100
1101         MonoExceptionClause *clauses;
1102         MonoExceptionClause *clause;
1103         MonoILExceptionInfo *ex_info;
1104         MonoILExceptionBlock *ex_block;
1105         guint32 finally_start;
1106         int i, j, clause_index;;
1107
1108         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1109
1110         clause_index = 0;
1111         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113                 finally_start = ex_info->start + ex_info->len;
1114                 if (!ex_info->handlers)
1115                         continue;
1116                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118                         clause = &(clauses [clause_index]);
1119
1120                         clause->flags = ex_block->type;
1121                         clause->try_offset = ex_info->start;
1122
1123                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124                                 clause->try_len = finally_start - ex_info->start;
1125                         else
1126                                 clause->try_len = ex_info->len;
1127                         clause->handler_offset = ex_block->start;
1128                         clause->handler_len = ex_block->len;
1129                         if (ex_block->extype) {
1130                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1131                         } else {
1132                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133                                         clause->data.filter_offset = ex_block->filter_offset;
1134                                 else
1135                                         clause->data.filter_offset = 0;
1136                         }
1137                         finally_start = ex_block->start + ex_block->len;
1138
1139                         clause_index ++;
1140                 }
1141         }
1142
1143         return clauses;
1144 }
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1146
1147 /**
1148  * method_encode_code:
1149  *
1150  * @assembly the assembly
1151  * @mb the managed MethodBuilder
1152  * @error set on error
1153  *
1154  * Note that the return value is not sensible if @error is set.
1155  */
1156 static guint32
1157 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1158 {
1159         MONO_REQ_GC_UNSAFE_MODE;
1160
1161         char flags = 0;
1162         guint32 idx;
1163         guint32 code_size;
1164         gint32 max_stack, i;
1165         gint32 num_locals = 0;
1166         gint32 num_exception = 0;
1167         gint maybe_small;
1168         guint32 fat_flags;
1169         char fat_header [12];
1170         guint32 int_value;
1171         guint16 short_value;
1172         guint32 local_sig = 0;
1173         guint32 header_size = 12;
1174         MonoArray *code;
1175
1176         mono_error_init (error);
1177
1178         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1179                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1180                 return 0;
1181
1182         /*if (mb->name)
1183                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1184         if (mb->ilgen) {
1185                 code = mb->ilgen->code;
1186                 code_size = mb->ilgen->code_len;
1187                 max_stack = mb->ilgen->max_stack;
1188                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1189                 if (mb->ilgen->ex_handlers)
1190                         num_exception = method_count_clauses (mb->ilgen);
1191         } else {
1192                 code = mb->code;
1193                 if (code == NULL){
1194                         char *name = mono_string_to_utf8 (mb->name);
1195                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1196                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1197                         g_free (str);
1198                         g_free (name);
1199                         return 0;
1200                 }
1201
1202                 code_size = mono_array_length (code);
1203                 max_stack = 8; /* we probably need to run a verifier on the code... */
1204         }
1205
1206         stream_data_align (&assembly->code);
1207
1208         /* check for exceptions, maxstack, locals */
1209         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1210         if (maybe_small) {
1211                 if (code_size < 64 && !(code_size & 1)) {
1212                         flags = (code_size << 2) | 0x2;
1213                 } else if (code_size < 32 && (code_size & 1)) {
1214                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1215                 } else {
1216                         goto fat_header;
1217                 }
1218                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1219                 /* add to the fixup todo list */
1220                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1221                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1222                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1223                 return assembly->text_rva + idx;
1224         } 
1225 fat_header:
1226         if (num_locals)
1227                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1228         /* 
1229          * FIXME: need to set also the header size in fat_flags.
1230          * (and more sects and init locals flags)
1231          */
1232         fat_flags =  0x03;
1233         if (num_exception)
1234                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1235         if (mb->init_locals)
1236                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1237         fat_header [0] = fat_flags;
1238         fat_header [1] = (header_size / 4 ) << 4;
1239         short_value = GUINT16_TO_LE (max_stack);
1240         memcpy (fat_header + 2, &short_value, 2);
1241         int_value = GUINT32_TO_LE (code_size);
1242         memcpy (fat_header + 4, &int_value, 4);
1243         int_value = GUINT32_TO_LE (local_sig);
1244         memcpy (fat_header + 8, &int_value, 4);
1245         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1246         /* add to the fixup todo list */
1247         if (mb->ilgen && mb->ilgen->num_token_fixups)
1248                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1249         
1250         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1251         if (num_exception) {
1252                 unsigned char sheader [4];
1253                 MonoILExceptionInfo * ex_info;
1254                 MonoILExceptionBlock * ex_block;
1255                 int j;
1256
1257                 stream_data_align (&assembly->code);
1258                 /* always use fat format for now */
1259                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1260                 num_exception *= 6 * sizeof (guint32);
1261                 num_exception += 4; /* include the size of the header */
1262                 sheader [1] = num_exception & 0xff;
1263                 sheader [2] = (num_exception >> 8) & 0xff;
1264                 sheader [3] = (num_exception >> 16) & 0xff;
1265                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1266                 /* fat header, so we are already aligned */
1267                 /* reverse order */
1268                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1269                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1270                         if (ex_info->handlers) {
1271                                 int finally_start = ex_info->start + ex_info->len;
1272                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1273                                         guint32 val;
1274                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1275                                         /* the flags */
1276                                         val = GUINT32_TO_LE (ex_block->type);
1277                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1278                                         /* try offset */
1279                                         val = GUINT32_TO_LE (ex_info->start);
1280                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1281                                         /* need fault, too, probably */
1282                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1283                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1284                                         else
1285                                                 val = GUINT32_TO_LE (ex_info->len);
1286                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1287                                         /* handler offset */
1288                                         val = GUINT32_TO_LE (ex_block->start);
1289                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1290                                         /* handler len */
1291                                         val = GUINT32_TO_LE (ex_block->len);
1292                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293                                         finally_start = ex_block->start + ex_block->len;
1294                                         if (ex_block->extype) {
1295                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1296                                         } else {
1297                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1298                                                         val = ex_block->filter_offset;
1299                                                 else
1300                                                         val = 0;
1301                                         }
1302                                         val = GUINT32_TO_LE (val);
1303                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1304                                         /*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", 
1305                                                         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);*/
1306                                 }
1307                         } else {
1308                                 g_error ("No clauses for ex info block %d", i);
1309                         }
1310                 }
1311         }
1312         return assembly->text_rva + idx;
1313 }
1314
1315 static guint32
1316 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1317 {
1318         MONO_REQ_GC_NEUTRAL_MODE;
1319
1320         int i;
1321         MonoDynamicTable *table;
1322         guint32 *values;
1323         
1324         table = &assembly->tables [table_idx];
1325
1326         g_assert (col < table->columns);
1327
1328         values = table->values + table->columns;
1329         for (i = 1; i <= table->rows; ++i) {
1330                 if (values [col] == token)
1331                         return i;
1332                 values += table->columns;
1333         }
1334         return 0;
1335 }
1336
1337 /*
1338  * LOCKING: Acquires the loader lock. 
1339  */
1340 static MonoCustomAttrInfo*
1341 lookup_custom_attr (MonoImage *image, gpointer member)
1342 {
1343         MONO_REQ_GC_NEUTRAL_MODE;
1344
1345         MonoCustomAttrInfo* res;
1346
1347         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1348
1349         if (!res)
1350                 return NULL;
1351
1352         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1353         res->cached = 0;
1354         return res;
1355 }
1356
1357 static gboolean
1358 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1359 {
1360         MONO_REQ_GC_UNSAFE_MODE;
1361
1362         /* FIXME: Need to do more checks */
1363         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1364                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1365
1366                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1367                         return FALSE;
1368         }
1369
1370         return TRUE;
1371 }
1372
1373 static MonoCustomAttrInfo*
1374 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1375 {
1376         MONO_REQ_GC_UNSAFE_MODE;
1377
1378         int i, index, count, not_visible;
1379         MonoCustomAttrInfo *ainfo;
1380         MonoReflectionCustomAttr *cattr;
1381
1382         if (!cattrs)
1383                 return NULL;
1384         /* FIXME: check in assembly the Run flag is set */
1385
1386         count = mono_array_length (cattrs);
1387
1388         /* Skip nonpublic attributes since MS.NET seems to do the same */
1389         /* FIXME: This needs to be done more globally */
1390         not_visible = 0;
1391         for (i = 0; i < count; ++i) {
1392                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1393                 if (!custom_attr_visible (image, cattr))
1394                         not_visible ++;
1395         }
1396         count -= not_visible;
1397
1398         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1399
1400         ainfo->image = image;
1401         ainfo->num_attrs = count;
1402         ainfo->cached = alloc_img != NULL;
1403         index = 0;
1404         for (i = 0; i < count; ++i) {
1405                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1406                 if (custom_attr_visible (image, cattr)) {
1407                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1408                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1409                         ainfo->attrs [index].ctor = cattr->ctor->method;
1410                         ainfo->attrs [index].data = saved;
1411                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1412                         index ++;
1413                 }
1414         }
1415
1416         return ainfo;
1417 }
1418
1419 #ifndef DISABLE_REFLECTION_EMIT
1420 /*
1421  * LOCKING: Acquires the loader lock. 
1422  */
1423 static void
1424 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1425 {
1426         MONO_REQ_GC_UNSAFE_MODE;
1427
1428         MonoCustomAttrInfo *ainfo, *tmp;
1429
1430         if (!cattrs || !mono_array_length (cattrs))
1431                 return;
1432
1433         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1434
1435         mono_loader_lock ();
1436         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1437         if (tmp)
1438                 mono_custom_attrs_free (tmp);
1439         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1440         mono_loader_unlock ();
1441
1442 }
1443 #endif
1444
1445 void
1446 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1447 {
1448         MONO_REQ_GC_NEUTRAL_MODE;
1449
1450         if (!ainfo->cached)
1451                 g_free (ainfo);
1452 }
1453
1454 /*
1455  * idx is the table index of the object
1456  * type is one of MONO_CUSTOM_ATTR_*
1457  */
1458 static gboolean
1459 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1460 {
1461         MONO_REQ_GC_UNSAFE_MODE;
1462
1463         MonoDynamicTable *table;
1464         MonoReflectionCustomAttr *cattr;
1465         guint32 *values;
1466         guint32 count, i, token;
1467         char blob_size [6];
1468         char *p = blob_size;
1469         
1470         mono_error_init (error);
1471
1472         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1473         if (!cattrs)
1474                 return TRUE;
1475         count = mono_array_length (cattrs);
1476         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1477         table->rows += count;
1478         alloc_table (table, table->rows);
1479         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1480         idx <<= MONO_CUSTOM_ATTR_BITS;
1481         idx |= type;
1482         for (i = 0; i < count; ++i) {
1483                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1485                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1486                 if (!mono_error_ok (error)) goto fail;
1487                 type = mono_metadata_token_index (token);
1488                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1489                 switch (mono_metadata_token_table (token)) {
1490                 case MONO_TABLE_METHOD:
1491                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1492                         /*
1493                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1494                          * method, not the one returned by mono_image_create_token ().
1495                          */
1496                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1497                         break;
1498                 case MONO_TABLE_MEMBERREF:
1499                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1500                         break;
1501                 default:
1502                         g_warning ("got wrong token in custom attr");
1503                         continue;
1504                 }
1505                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1506                 p = blob_size;
1507                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1508                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1509                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1510                 values += MONO_CUSTOM_ATTR_SIZE;
1511                 ++table->next_idx;
1512         }
1513
1514         return TRUE;
1515
1516 fail:
1517         return FALSE;
1518 }
1519
1520 static void
1521 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1522 {
1523         MONO_REQ_GC_UNSAFE_MODE;
1524
1525         MonoDynamicTable *table;
1526         guint32 *values;
1527         guint32 count, i, idx;
1528         MonoReflectionPermissionSet *perm;
1529
1530         if (!permissions)
1531                 return;
1532
1533         count = mono_array_length (permissions);
1534         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1535         table->rows += count;
1536         alloc_table (table, table->rows);
1537
1538         for (i = 0; i < mono_array_length (permissions); ++i) {
1539                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1540
1541                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1542
1543                 idx = mono_metadata_token_index (parent_token);
1544                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1545                 switch (mono_metadata_token_table (parent_token)) {
1546                 case MONO_TABLE_TYPEDEF:
1547                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1548                         break;
1549                 case MONO_TABLE_METHOD:
1550                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1551                         break;
1552                 case MONO_TABLE_ASSEMBLY:
1553                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1554                         break;
1555                 default:
1556                         g_assert_not_reached ();
1557                 }
1558
1559                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1560                 values [MONO_DECL_SECURITY_PARENT] = idx;
1561                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1562
1563                 ++table->next_idx;
1564         }
1565 }
1566
1567 /*
1568  * Fill in the MethodDef and ParamDef tables for a method.
1569  * This is used for both normal methods and constructors.
1570  */
1571 static gboolean
1572 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1573 {
1574         MONO_REQ_GC_UNSAFE_MODE;
1575
1576         MonoDynamicTable *table;
1577         guint32 *values;
1578         guint i, count;
1579
1580         mono_error_init (error);
1581
1582         /* room in this table is already allocated */
1583         table = &assembly->tables [MONO_TABLE_METHOD];
1584         *mb->table_idx = table->next_idx ++;
1585         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1586         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1587         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1588         values [MONO_METHOD_FLAGS] = mb->attrs;
1589         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1590         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1591         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1592         if (!mono_error_ok (error))
1593                 return FALSE;
1594
1595         table = &assembly->tables [MONO_TABLE_PARAM];
1596         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1597
1598         mono_image_add_decl_security (assembly, 
1599                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1600
1601         if (mb->pinfo) {
1602                 MonoDynamicTable *mtable;
1603                 guint32 *mvalues;
1604                 
1605                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1606                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1607                 
1608                 count = 0;
1609                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1610                         if (mono_array_get (mb->pinfo, gpointer, i))
1611                                 count++;
1612                 }
1613                 table->rows += count;
1614                 alloc_table (table, table->rows);
1615                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1616                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1617                         MonoReflectionParamBuilder *pb;
1618                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1619                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1620                                 values [MONO_PARAM_SEQUENCE] = i;
1621                                 if (pb->name != NULL) {
1622                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1623                                 } else {
1624                                         values [MONO_PARAM_NAME] = 0;
1625                                 }
1626                                 values += MONO_PARAM_SIZE;
1627                                 if (pb->marshal_info) {
1628                                         mtable->rows++;
1629                                         alloc_table (mtable, mtable->rows);
1630                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1631                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1632                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1633                                 }
1634                                 pb->table_idx = table->next_idx++;
1635                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1636                                         guint32 field_type = 0;
1637                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1638                                         mtable->rows ++;
1639                                         alloc_table (mtable, mtable->rows);
1640                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1641                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1642                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1643                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1644                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1645                                 }
1646                         }
1647                 }
1648         }
1649
1650         return TRUE;
1651 }
1652
1653 #ifndef DISABLE_REFLECTION_EMIT
1654 static void
1655 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1656 {
1657         MonoError error;
1658         MONO_REQ_GC_UNSAFE_MODE;
1659
1660         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1661
1662         rmb->ilgen = mb->ilgen;
1663         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, &error);
1664         mono_error_raise_exception (&error); /* FIXME don't raise here */
1665         rmb->parameters = mb->parameters;
1666         rmb->generic_params = mb->generic_params;
1667         rmb->generic_container = mb->generic_container;
1668         rmb->opt_types = NULL;
1669         rmb->pinfo = mb->pinfo;
1670         rmb->attrs = mb->attrs;
1671         rmb->iattrs = mb->iattrs;
1672         rmb->call_conv = mb->call_conv;
1673         rmb->code = mb->code;
1674         rmb->type = mb->type;
1675         rmb->name = mb->name;
1676         rmb->table_idx = &mb->table_idx;
1677         rmb->init_locals = mb->init_locals;
1678         rmb->skip_visibility = FALSE;
1679         rmb->return_modreq = mb->return_modreq;
1680         rmb->return_modopt = mb->return_modopt;
1681         rmb->param_modreq = mb->param_modreq;
1682         rmb->param_modopt = mb->param_modopt;
1683         rmb->permissions = mb->permissions;
1684         rmb->mhandle = mb->mhandle;
1685         rmb->nrefs = 0;
1686         rmb->refs = NULL;
1687
1688         if (mb->dll) {
1689                 rmb->charset = mb->charset;
1690                 rmb->extra_flags = mb->extra_flags;
1691                 rmb->native_cc = mb->native_cc;
1692                 rmb->dllentry = mb->dllentry;
1693                 rmb->dll = mb->dll;
1694         }
1695 }
1696
1697 static void
1698 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1699 {
1700         MONO_REQ_GC_UNSAFE_MODE;
1701
1702         MonoError error;
1703         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1704
1705         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1706
1707         rmb->ilgen = mb->ilgen;
1708         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1709         mono_error_raise_exception (&error); /* FIXME don't raise here */
1710         rmb->parameters = mb->parameters;
1711         rmb->generic_params = NULL;
1712         rmb->generic_container = NULL;
1713         rmb->opt_types = NULL;
1714         rmb->pinfo = mb->pinfo;
1715         rmb->attrs = mb->attrs;
1716         rmb->iattrs = mb->iattrs;
1717         rmb->call_conv = mb->call_conv;
1718         rmb->code = NULL;
1719         rmb->type = mb->type;
1720         rmb->name = mono_string_new (mono_domain_get (), name);
1721         rmb->table_idx = &mb->table_idx;
1722         rmb->init_locals = mb->init_locals;
1723         rmb->skip_visibility = FALSE;
1724         rmb->return_modreq = NULL;
1725         rmb->return_modopt = NULL;
1726         rmb->param_modreq = mb->param_modreq;
1727         rmb->param_modopt = mb->param_modopt;
1728         rmb->permissions = mb->permissions;
1729         rmb->mhandle = mb->mhandle;
1730         rmb->nrefs = 0;
1731         rmb->refs = NULL;
1732 }
1733
1734 static void
1735 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1736 {
1737         MONO_REQ_GC_UNSAFE_MODE;
1738
1739         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1740
1741         rmb->ilgen = mb->ilgen;
1742         rmb->rtype = mb->rtype;
1743         rmb->parameters = mb->parameters;
1744         rmb->generic_params = NULL;
1745         rmb->generic_container = NULL;
1746         rmb->opt_types = NULL;
1747         rmb->pinfo = NULL;
1748         rmb->attrs = mb->attrs;
1749         rmb->iattrs = 0;
1750         rmb->call_conv = mb->call_conv;
1751         rmb->code = NULL;
1752         rmb->type = (MonoObject *) mb->owner;
1753         rmb->name = mb->name;
1754         rmb->table_idx = NULL;
1755         rmb->init_locals = mb->init_locals;
1756         rmb->skip_visibility = mb->skip_visibility;
1757         rmb->return_modreq = NULL;
1758         rmb->return_modopt = NULL;
1759         rmb->param_modreq = NULL;
1760         rmb->param_modopt = NULL;
1761         rmb->permissions = NULL;
1762         rmb->mhandle = mb->mhandle;
1763         rmb->nrefs = 0;
1764         rmb->refs = NULL;
1765 }       
1766 #endif
1767
1768 static gboolean
1769 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1770 {
1771         MONO_REQ_GC_UNSAFE_MODE;
1772
1773         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1774         MonoDynamicTable *table;
1775         guint32 *values;
1776         guint32 tok;
1777         MonoReflectionMethod *m;
1778         int i;
1779
1780         mono_error_init (error);
1781
1782         if (!mb->override_methods)
1783                 return TRUE;
1784
1785         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1786                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1787
1788                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1789                 table->rows ++;
1790                 alloc_table (table, table->rows);
1791                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1792                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1793                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1794
1795                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1796                 return_val_if_nok (error, FALSE);
1797
1798                 switch (mono_metadata_token_table (tok)) {
1799                 case MONO_TABLE_MEMBERREF:
1800                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1801                         break;
1802                 case MONO_TABLE_METHOD:
1803                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1804                         break;
1805                 default:
1806                         g_assert_not_reached ();
1807                 }
1808                 values [MONO_METHODIMPL_DECLARATION] = tok;
1809         }
1810
1811         return TRUE;
1812 }
1813
1814 #ifndef DISABLE_REFLECTION_EMIT
1815 static void
1816 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1817 {
1818         MONO_REQ_GC_UNSAFE_MODE;
1819
1820         MonoError error;
1821
1822         MonoDynamicTable *table;
1823         guint32 *values;
1824         ReflectionMethodBuilder rmb;
1825         int i;
1826
1827         reflection_methodbuilder_from_method_builder (&rmb, mb);
1828
1829         mono_image_basic_method (&rmb, assembly, &error);
1830         mono_error_raise_exception (&error); /* FIXME don't raise here */
1831         mb->table_idx = *rmb.table_idx;
1832
1833         if (mb->dll) { /* It's a P/Invoke method */
1834                 guint32 moduleref;
1835                 /* map CharSet values to on-disk values */
1836                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1837                 int extra_flags = mb->extra_flags;
1838                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1839                 table->rows ++;
1840                 alloc_table (table, table->rows);
1841                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1842                 
1843                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1844                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1845                 if (mb->dllentry)
1846                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1847                 else
1848                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1849                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1850                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1851                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1852                         table->rows ++;
1853                         alloc_table (table, table->rows);
1854                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1855                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1856                 }
1857         }
1858
1859         if (mb->generic_params) {
1860                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1861                 table->rows += mono_array_length (mb->generic_params);
1862                 alloc_table (table, table->rows);
1863                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1864                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1865
1866                         mono_image_get_generic_param_info (
1867                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1868                 }
1869         }
1870
1871 }
1872
1873 static gboolean
1874 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1875 {
1876         MONO_REQ_GC_UNSAFE_MODE;
1877
1878         ReflectionMethodBuilder rmb;
1879
1880         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1881
1882         if (!mono_image_basic_method (&rmb, assembly, error))
1883                 return FALSE;
1884
1885         mb->table_idx = *rmb.table_idx;
1886
1887         return TRUE;
1888 }
1889 #endif
1890
1891 static char*
1892 type_get_fully_qualified_name (MonoType *type)
1893 {
1894         MONO_REQ_GC_NEUTRAL_MODE;
1895
1896         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1897 }
1898
1899 static char*
1900 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1901 {
1902         MONO_REQ_GC_UNSAFE_MODE;
1903
1904         MonoClass *klass;
1905         MonoAssembly *ta;
1906
1907         klass = mono_class_from_mono_type (type);
1908         if (!klass) 
1909                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1910         ta = klass->image->assembly;
1911         if (assembly_is_dynamic (ta) || (ta == ass)) {
1912                 if (klass->generic_class || klass->generic_container)
1913                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1914                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1915                 else
1916                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1917         }
1918
1919         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1920 }
1921
1922 #ifndef DISABLE_REFLECTION_EMIT
1923 /*field_image is the image to which the eventual custom mods have been encoded against*/
1924 static guint32
1925 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1926 {
1927         MONO_REQ_GC_NEUTRAL_MODE;
1928
1929         SigBuffer buf;
1930         guint32 idx, i, token;
1931
1932         if (!assembly->save)
1933                 return 0;
1934
1935         sigbuffer_init (&buf, 32);
1936         
1937         sigbuffer_add_value (&buf, 0x06);
1938         /* encode custom attributes before the type */
1939         if (type->num_mods) {
1940                 for (i = 0; i < type->num_mods; ++i) {
1941                         if (field_image) {
1942                                 MonoError error;
1943                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1944                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1945
1946                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1947                         } else {
1948                                 token = type->modifiers [i].token;
1949                         }
1950
1951                         if (type->modifiers [i].required)
1952                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1953                         else
1954                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1955
1956                         sigbuffer_add_value (&buf, token);
1957                 }
1958         }
1959         encode_type (assembly, type, &buf);
1960         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961         sigbuffer_free (&buf);
1962         return idx;
1963 }
1964 #endif
1965
1966 static guint32
1967 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1968 {
1969         MONO_REQ_GC_UNSAFE_MODE;
1970
1971         SigBuffer buf;
1972         guint32 idx;
1973         guint32 typespec = 0;
1974         MonoType *type;
1975         MonoClass *klass;
1976
1977         init_type_builder_generics (fb->type);
1978
1979         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1980         klass = mono_class_from_mono_type (type);
1981
1982         sigbuffer_init (&buf, 32);
1983         
1984         sigbuffer_add_value (&buf, 0x06);
1985         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1986         /* encode custom attributes before the type */
1987
1988         if (klass->generic_container)
1989                 typespec = create_typespec (assembly, type);
1990
1991         if (typespec) {
1992                 MonoGenericClass *gclass;
1993                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1994                 encode_generic_class (assembly, gclass, &buf);
1995         } else {
1996                 encode_type (assembly, type, &buf);
1997         }
1998         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1999         sigbuffer_free (&buf);
2000         return idx;
2001 }
2002
2003 static guint32
2004 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2005 {
2006         MONO_REQ_GC_UNSAFE_MODE;
2007
2008         char blob_size [64];
2009         char *b = blob_size;
2010         char *box_val;
2011         char* buf;
2012         guint32 idx = 0, len = 0, dummy = 0;
2013
2014         buf = (char *)g_malloc (64);
2015         if (!val) {
2016                 *ret_type = MONO_TYPE_CLASS;
2017                 len = 4;
2018                 box_val = (char*)&dummy;
2019         } else {
2020                 box_val = ((char*)val) + sizeof (MonoObject);
2021                 *ret_type = val->vtable->klass->byval_arg.type;
2022         }
2023 handle_enum:
2024         switch (*ret_type) {
2025         case MONO_TYPE_BOOLEAN:
2026         case MONO_TYPE_U1:
2027         case MONO_TYPE_I1:
2028                 len = 1;
2029                 break;
2030         case MONO_TYPE_CHAR:
2031         case MONO_TYPE_U2:
2032         case MONO_TYPE_I2:
2033                 len = 2;
2034                 break;
2035         case MONO_TYPE_U4:
2036         case MONO_TYPE_I4:
2037         case MONO_TYPE_R4:
2038                 len = 4;
2039                 break;
2040         case MONO_TYPE_U8:
2041         case MONO_TYPE_I8:
2042                 len = 8;
2043                 break;
2044         case MONO_TYPE_R8:
2045                 len = 8;
2046                 break;
2047         case MONO_TYPE_VALUETYPE: {
2048                 MonoClass *klass = val->vtable->klass;
2049                 
2050                 if (klass->enumtype) {
2051                         *ret_type = mono_class_enum_basetype (klass)->type;
2052                         goto handle_enum;
2053                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2054                         len = 8;
2055                 } else 
2056                         g_error ("we can't encode valuetypes, we should have never reached this line");
2057                 break;
2058         }
2059         case MONO_TYPE_CLASS:
2060                 break;
2061         case MONO_TYPE_STRING: {
2062                 MonoString *str = (MonoString*)val;
2063                 /* there is no signature */
2064                 len = str->length * 2;
2065                 mono_metadata_encode_value (len, b, &b);
2066 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2067                 {
2068                         char *swapped = g_malloc (2 * mono_string_length (str));
2069                         const char *p = (const char*)mono_string_chars (str);
2070
2071                         swap_with_size (swapped, p, 2, mono_string_length (str));
2072                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2073                         g_free (swapped);
2074                 }
2075 #else
2076                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2077 #endif
2078
2079                 g_free (buf);
2080                 return idx;
2081         }
2082         case MONO_TYPE_GENERICINST:
2083                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2084                 goto handle_enum;
2085         default:
2086                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2087         }
2088
2089         /* there is no signature */
2090         mono_metadata_encode_value (len, b, &b);
2091 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2092         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2093         swap_with_size (blob_size, box_val, len, 1);
2094         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2095 #else
2096         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2097 #endif
2098
2099         g_free (buf);
2100         return idx;
2101 }
2102
2103 static guint32
2104 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2105 {
2106         MONO_REQ_GC_UNSAFE_MODE;
2107
2108         char *str;
2109         SigBuffer buf;
2110         guint32 idx, len;
2111
2112         sigbuffer_init (&buf, 32);
2113
2114         sigbuffer_add_value (&buf, minfo->type);
2115
2116         switch (minfo->type) {
2117         case MONO_NATIVE_BYVALTSTR:
2118         case MONO_NATIVE_BYVALARRAY:
2119                 sigbuffer_add_value (&buf, minfo->count);
2120                 break;
2121         case MONO_NATIVE_LPARRAY:
2122                 if (minfo->eltype || minfo->has_size) {
2123                         sigbuffer_add_value (&buf, minfo->eltype);
2124                         if (minfo->has_size) {
2125                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2126                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2127
2128                                 /* LAMESPEC: ElemMult is undocumented */
2129                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2130                         }
2131                 }
2132                 break;
2133         case MONO_NATIVE_SAFEARRAY:
2134                 if (minfo->eltype)
2135                         sigbuffer_add_value (&buf, minfo->eltype);
2136                 break;
2137         case MONO_NATIVE_CUSTOM:
2138                 if (minfo->guid) {
2139                         str = mono_string_to_utf8 (minfo->guid);
2140                         len = strlen (str);
2141                         sigbuffer_add_value (&buf, len);
2142                         sigbuffer_add_mem (&buf, str, len);
2143                         g_free (str);
2144                 } else {
2145                         sigbuffer_add_value (&buf, 0);
2146                 }
2147                 /* native type name */
2148                 sigbuffer_add_value (&buf, 0);
2149                 /* custom marshaler type name */
2150                 if (minfo->marshaltype || minfo->marshaltyperef) {
2151                         if (minfo->marshaltyperef)
2152                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2153                         else
2154                                 str = mono_string_to_utf8 (minfo->marshaltype);
2155                         len = strlen (str);
2156                         sigbuffer_add_value (&buf, len);
2157                         sigbuffer_add_mem (&buf, str, len);
2158                         g_free (str);
2159                 } else {
2160                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2161                         sigbuffer_add_value (&buf, 0);
2162                 }
2163                 if (minfo->mcookie) {
2164                         str = mono_string_to_utf8 (minfo->mcookie);
2165                         len = strlen (str);
2166                         sigbuffer_add_value (&buf, len);
2167                         sigbuffer_add_mem (&buf, str, len);
2168                         g_free (str);
2169                 } else {
2170                         sigbuffer_add_value (&buf, 0);
2171                 }
2172                 break;
2173         default:
2174                 break;
2175         }
2176         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2177         sigbuffer_free (&buf);
2178         return idx;
2179 }
2180
2181 static void
2182 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2183 {
2184         MONO_REQ_GC_UNSAFE_MODE;
2185
2186         MonoDynamicTable *table;
2187         guint32 *values;
2188
2189         /* maybe this fixup should be done in the C# code */
2190         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2191                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2192         table = &assembly->tables [MONO_TABLE_FIELD];
2193         fb->table_idx = table->next_idx ++;
2194         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2195         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2196         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2197         values [MONO_FIELD_FLAGS] = fb->attrs;
2198         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2199
2200         if (fb->offset != -1) {
2201                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2202                 table->rows ++;
2203                 alloc_table (table, table->rows);
2204                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2205                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2206                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2207         }
2208         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2209                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2210                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2211                 table->rows ++;
2212                 alloc_table (table, table->rows);
2213                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2214                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2215                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2216                 values [MONO_CONSTANT_TYPE] = field_type;
2217                 values [MONO_CONSTANT_PADDING] = 0;
2218         }
2219         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2220                 guint32 rva_idx;
2221                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2222                 table->rows ++;
2223                 alloc_table (table, table->rows);
2224                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2225                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2226                 /*
2227                  * We store it in the code section because it's simpler for now.
2228                  */
2229                 if (fb->rva_data) {
2230                         if (mono_array_length (fb->rva_data) >= 10)
2231                                 stream_data_align (&assembly->code);
2232                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2233                 } else
2234                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2235                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2236         }
2237         if (fb->marshal_info) {
2238                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2239                 table->rows ++;
2240                 alloc_table (table, table->rows);
2241                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2242                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2243                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2244         }
2245 }
2246
2247 static guint32
2248 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2249 {
2250         MONO_REQ_GC_UNSAFE_MODE;
2251
2252         SigBuffer buf;
2253         guint32 nparams = 0;
2254         MonoReflectionMethodBuilder *mb = fb->get_method;
2255         MonoReflectionMethodBuilder *smb = fb->set_method;
2256         guint32 idx, i;
2257
2258         if (mb && mb->parameters)
2259                 nparams = mono_array_length (mb->parameters);
2260         if (!mb && smb && smb->parameters)
2261                 nparams = mono_array_length (smb->parameters) - 1;
2262         sigbuffer_init (&buf, 32);
2263         if (fb->call_conv & 0x20)
2264                 sigbuffer_add_byte (&buf, 0x28);
2265         else
2266                 sigbuffer_add_byte (&buf, 0x08);
2267         sigbuffer_add_value (&buf, nparams);
2268         if (mb) {
2269                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2270                 for (i = 0; i < nparams; ++i) {
2271                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2272                         encode_reflection_type (assembly, pt, &buf);
2273                 }
2274         } else if (smb && smb->parameters) {
2275                 /* the property type is the last param */
2276                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2277                 for (i = 0; i < nparams; ++i) {
2278                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2279                         encode_reflection_type (assembly, pt, &buf);
2280                 }
2281         } else {
2282                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2283         }
2284
2285         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2286         sigbuffer_free (&buf);
2287         return idx;
2288 }
2289
2290 static void
2291 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2292 {
2293         MONO_REQ_GC_UNSAFE_MODE;
2294
2295         MonoDynamicTable *table;
2296         guint32 *values;
2297         guint num_methods = 0;
2298         guint32 semaidx;
2299
2300         /* 
2301          * we need to set things in the following tables:
2302          * PROPERTYMAP (info already filled in _get_type_info ())
2303          * PROPERTY    (rows already preallocated in _get_type_info ())
2304          * METHOD      (method info already done with the generic method code)
2305          * METHODSEMANTICS
2306          * CONSTANT
2307          */
2308         table = &assembly->tables [MONO_TABLE_PROPERTY];
2309         pb->table_idx = table->next_idx ++;
2310         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2311         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2312         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2313         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2314
2315         /* FIXME: we still don't handle 'other' methods */
2316         if (pb->get_method) num_methods ++;
2317         if (pb->set_method) num_methods ++;
2318
2319         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2320         table->rows += num_methods;
2321         alloc_table (table, table->rows);
2322
2323         if (pb->get_method) {
2324                 semaidx = table->next_idx ++;
2325                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2326                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2327                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2328                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2329         }
2330         if (pb->set_method) {
2331                 semaidx = table->next_idx ++;
2332                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2333                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2334                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2335                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2336         }
2337         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2338                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2339                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2340                 table->rows ++;
2341                 alloc_table (table, table->rows);
2342                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2343                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2344                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2345                 values [MONO_CONSTANT_TYPE] = field_type;
2346                 values [MONO_CONSTANT_PADDING] = 0;
2347         }
2348 }
2349
2350 static void
2351 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2352 {
2353         MONO_REQ_GC_UNSAFE_MODE;
2354
2355         MonoDynamicTable *table;
2356         guint32 *values;
2357         guint num_methods = 0;
2358         guint32 semaidx;
2359
2360         /* 
2361          * we need to set things in the following tables:
2362          * EVENTMAP (info already filled in _get_type_info ())
2363          * EVENT    (rows already preallocated in _get_type_info ())
2364          * METHOD      (method info already done with the generic method code)
2365          * METHODSEMANTICS
2366          */
2367         table = &assembly->tables [MONO_TABLE_EVENT];
2368         eb->table_idx = table->next_idx ++;
2369         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2370         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2371         values [MONO_EVENT_FLAGS] = eb->attrs;
2372         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2373
2374         /*
2375          * FIXME: we still don't handle 'other' methods 
2376          */
2377         if (eb->add_method) num_methods ++;
2378         if (eb->remove_method) num_methods ++;
2379         if (eb->raise_method) num_methods ++;
2380
2381         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2382         table->rows += num_methods;
2383         alloc_table (table, table->rows);
2384
2385         if (eb->add_method) {
2386                 semaidx = table->next_idx ++;
2387                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2388                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2389                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2390                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2391         }
2392         if (eb->remove_method) {
2393                 semaidx = table->next_idx ++;
2394                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2395                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2396                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2397                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2398         }
2399         if (eb->raise_method) {
2400                 semaidx = table->next_idx ++;
2401                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2402                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2403                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2404                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2405         }
2406 }
2407
2408 static void
2409 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2410 {
2411         MONO_REQ_GC_UNSAFE_MODE;
2412
2413         MonoDynamicTable *table;
2414         guint32 num_constraints, i;
2415         guint32 *values;
2416         guint32 table_idx;
2417
2418         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2419         num_constraints = gparam->iface_constraints ?
2420                 mono_array_length (gparam->iface_constraints) : 0;
2421         table->rows += num_constraints;
2422         if (gparam->base_type)
2423                 table->rows++;
2424         alloc_table (table, table->rows);
2425
2426         if (gparam->base_type) {
2427                 table_idx = table->next_idx ++;
2428                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2429
2430                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2431                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2432                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2433         }
2434
2435         for (i = 0; i < num_constraints; i++) {
2436                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2437                         gparam->iface_constraints, gpointer, i);
2438
2439                 table_idx = table->next_idx ++;
2440                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2441
2442                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2443                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2444                         assembly, mono_reflection_type_get_handle (constraint));
2445         }
2446 }
2447
2448 static void
2449 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2450 {
2451         MONO_REQ_GC_UNSAFE_MODE;
2452
2453         GenericParamTableEntry *entry;
2454
2455         /*
2456          * The GenericParam table must be sorted according to the `owner' field.
2457          * We need to do this sorting prior to writing the GenericParamConstraint
2458          * table, since we have to use the final GenericParam table indices there
2459          * and they must also be sorted.
2460          */
2461
2462         entry = g_new0 (GenericParamTableEntry, 1);
2463         entry->owner = owner;
2464         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2465         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2466         entry->gparam = gparam;
2467         
2468         g_ptr_array_add (assembly->gen_params, entry);
2469 }
2470
2471 static void
2472 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2473 {
2474         MONO_REQ_GC_UNSAFE_MODE;
2475
2476         MonoError error;
2477
2478         MonoDynamicTable *table;
2479         MonoGenericParam *param;
2480         guint32 *values;
2481         guint32 table_idx;
2482
2483         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2484         table_idx = table->next_idx ++;
2485         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2486
2487         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2488
2489         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2490         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2491         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2492         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2493
2494         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, &error))
2495                 goto fail;
2496
2497         encode_constraints (entry->gparam, table_idx, assembly);
2498         return;
2499
2500 fail:
2501         mono_error_raise_exception (&error); /* FIXME don't raise here */
2502 }
2503
2504 static guint32
2505 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2506 {
2507         MONO_REQ_GC_UNSAFE_MODE;
2508
2509         MonoDynamicTable *table;
2510         guint32 token;
2511         guint32 *values;
2512         guint32 cols [MONO_ASSEMBLY_SIZE];
2513         const char *pubkey;
2514         guint32 publen;
2515
2516         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2517                 return token;
2518
2519         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2520                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2521                 token = table->next_idx ++;
2522                 table->rows ++;
2523                 alloc_table (table, table->rows);
2524                 values = table->values + token * MONO_MODULEREF_SIZE;
2525                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2526
2527                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2528                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2529                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2530
2531                 return token;
2532         }
2533         
2534         if (assembly_is_dynamic (image->assembly))
2535                 /* FIXME: */
2536                 memset (cols, 0, sizeof (cols));
2537         else {
2538                 /* image->assembly->image is the manifest module */
2539                 image = image->assembly->image;
2540                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2541         }
2542
2543         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2544         token = table->next_idx ++;
2545         table->rows ++;
2546         alloc_table (table, table->rows);
2547         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2548         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2549         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2550         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2551         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2552         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2553         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2554         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2555         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2556
2557         if (strcmp ("", image->assembly->aname.culture)) {
2558                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2559                                 image->assembly->aname.culture);
2560         }
2561
2562         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2563                 guchar pubtoken [9];
2564                 pubtoken [0] = 8;
2565                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2566                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2567         } else {
2568                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2569         }
2570         token <<= MONO_RESOLUTION_SCOPE_BITS;
2571         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2572         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2573         return token;
2574 }
2575
2576 static guint32
2577 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2578 {
2579         MONO_REQ_GC_NEUTRAL_MODE;
2580
2581         MonoDynamicTable *table;
2582         guint32 *values;
2583         guint32 token;
2584         SigBuffer buf;
2585
2586         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2587                 return token;
2588
2589         sigbuffer_init (&buf, 32);
2590         switch (type->type) {
2591         case MONO_TYPE_FNPTR:
2592         case MONO_TYPE_PTR:
2593         case MONO_TYPE_SZARRAY:
2594         case MONO_TYPE_ARRAY:
2595         case MONO_TYPE_VAR:
2596         case MONO_TYPE_MVAR:
2597         case MONO_TYPE_GENERICINST:
2598                 encode_type (assembly, type, &buf);
2599                 break;
2600         case MONO_TYPE_CLASS:
2601         case MONO_TYPE_VALUETYPE: {
2602                 MonoClass *k = mono_class_from_mono_type (type);
2603                 if (!k || !k->generic_container) {
2604                         sigbuffer_free (&buf);
2605                         return 0;
2606                 }
2607                 encode_type (assembly, type, &buf);
2608                 break;
2609         }
2610         default:
2611                 sigbuffer_free (&buf);
2612                 return 0;
2613         }
2614
2615         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2616         if (assembly->save) {
2617                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2618                 alloc_table (table, table->rows + 1);
2619                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2620                 values [MONO_TYPESPEC_SIGNATURE] = token;
2621         }
2622         sigbuffer_free (&buf);
2623
2624         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2625         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2626         table->next_idx ++;
2627         return token;
2628 }
2629
2630 static guint32
2631 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2632 {
2633         MONO_REQ_GC_UNSAFE_MODE;
2634
2635         MonoDynamicTable *table;
2636         guint32 *values;
2637         guint32 token, scope, enclosing;
2638         MonoClass *klass;
2639
2640         /* if the type requires a typespec, we must try that first*/
2641         if (try_typespec && (token = create_typespec (assembly, type)))
2642                 return token;
2643         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2644         if (token)
2645                 return token;
2646         klass = mono_class_from_mono_type (type);
2647         if (!klass)
2648                 klass = mono_class_from_mono_type (type);
2649
2650         /*
2651          * If it's in the same module and not a generic type parameter:
2652          */
2653         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2654                         (type->type != MONO_TYPE_MVAR)) {
2655                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2656                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2657                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2658                 return token;
2659         }
2660
2661         if (klass->nested_in) {
2662                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2663                 /* get the typeref idx of the enclosing type */
2664                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2665                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2666         } else {
2667                 scope = resolution_scope_from_image (assembly, klass->image);
2668         }
2669         table = &assembly->tables [MONO_TABLE_TYPEREF];
2670         if (assembly->save) {
2671                 alloc_table (table, table->rows + 1);
2672                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2673                 values [MONO_TYPEREF_SCOPE] = scope;
2674                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2675                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2676         }
2677         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2678         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2679         table->next_idx ++;
2680         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2681         return token;
2682 }
2683
2684 /*
2685  * Despite the name, we handle also TypeSpec (with the above helper).
2686  */
2687 static guint32
2688 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2689 {
2690         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2691 }
2692
2693 #ifndef DISABLE_REFLECTION_EMIT
2694 static guint32
2695 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2696 {
2697         MONO_REQ_GC_NEUTRAL_MODE;
2698
2699         MonoDynamicTable *table;
2700         guint32 *values;
2701         guint32 token, pclass;
2702
2703         switch (parent & MONO_TYPEDEFORREF_MASK) {
2704         case MONO_TYPEDEFORREF_TYPEREF:
2705                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2706                 break;
2707         case MONO_TYPEDEFORREF_TYPESPEC:
2708                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2709                 break;
2710         case MONO_TYPEDEFORREF_TYPEDEF:
2711                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2712                 break;
2713         default:
2714                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2715                 return 0;
2716         }
2717         /* extract the index */
2718         parent >>= MONO_TYPEDEFORREF_BITS;
2719
2720         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2721
2722         if (assembly->save) {
2723                 alloc_table (table, table->rows + 1);
2724                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2725                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2726                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2727                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2728         }
2729
2730         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2731         table->next_idx ++;
2732
2733         return token;
2734 }
2735
2736 /*
2737  * Insert a memberef row into the metadata: the token that point to the memberref
2738  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2739  * mono_image_get_fieldref_token()).
2740  * The sig param is an index to an already built signature.
2741  */
2742 static guint32
2743 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2744 {
2745         MONO_REQ_GC_NEUTRAL_MODE;
2746
2747         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2748         return mono_image_add_memberef_row (assembly, parent, name, sig);
2749 }
2750
2751
2752 static guint32
2753 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2754 {
2755         MONO_REQ_GC_NEUTRAL_MODE;
2756
2757         guint32 token;
2758         MonoMethodSignature *sig;
2759         
2760         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2761
2762         if (create_typespec) {
2763                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2764                 if (token)
2765                         return token;
2766         } 
2767
2768         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2769         if (token && !create_typespec)
2770                 return token;
2771
2772         g_assert (!method->is_inflated);
2773         if (!token) {
2774                 /*
2775                  * A methodref signature can't contain an unmanaged calling convention.
2776                  */
2777                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2778                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2779                         sig->call_convention = MONO_CALL_DEFAULT;
2780                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2781                         method->name,  method_encode_signature (assembly, sig));
2782                 g_free (sig);
2783                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2784         }
2785
2786         if (create_typespec) {
2787                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2788                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2789                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2790
2791                 if (assembly->save) {
2792                         guint32 *values;
2793
2794                         alloc_table (table, table->rows + 1);
2795                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2796                         values [MONO_METHODSPEC_METHOD] = token;
2797                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2798                 }
2799
2800                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2801                 table->next_idx ++;
2802                 /*methodspec and memberef tokens are diferent, */
2803                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2804                 return token;
2805         }
2806         return token;
2807 }
2808
2809 static guint32
2810 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2811 {
2812         guint32 token, parent, sig;
2813         ReflectionMethodBuilder rmb;
2814         char *name;
2815         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2816         
2817         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2818         if (token)
2819                 return token;
2820
2821         name = mono_string_to_utf8 (method->name);
2822         reflection_methodbuilder_from_method_builder (&rmb, method);
2823
2824         /*
2825          * A methodref signature can't contain an unmanaged calling convention.
2826          * Since some flags are encoded as part of call_conv, we need to check against it.
2827         */
2828         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2829                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2830
2831         sig = method_builder_encode_signature (assembly, &rmb);
2832
2833         if (tb->generic_params)
2834                 parent = create_generic_typespec (assembly, tb);
2835         else
2836                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2837
2838         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2839
2840         g_free (name);
2841         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2842         return token;
2843 }
2844
2845 static guint32
2846 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2847                                      const gchar *name, guint32 sig)
2848 {
2849         MonoDynamicTable *table;
2850         guint32 token;
2851         guint32 *values;
2852         
2853         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2854
2855         if (assembly->save) {
2856                 alloc_table (table, table->rows + 1);
2857                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2858                 values [MONO_MEMBERREF_CLASS] = original;
2859                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2860                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2861         }
2862
2863         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2864         table->next_idx ++;
2865
2866         return token;
2867 }
2868
2869 static guint32
2870 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2871 {
2872         SigBuffer buf;
2873         int i;
2874         guint32 nparams = mono_array_length (mb->generic_params);
2875         guint32 idx;
2876
2877         if (!assembly->save)
2878                 return 0;
2879
2880         sigbuffer_init (&buf, 32);
2881
2882         sigbuffer_add_value (&buf, 0xa);
2883         sigbuffer_add_value (&buf, nparams);
2884
2885         for (i = 0; i < nparams; i++) {
2886                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2887                 sigbuffer_add_value (&buf, i);
2888         }
2889
2890         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2891         sigbuffer_free (&buf);
2892         return idx;
2893 }
2894
2895 static guint32
2896 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2897 {
2898         MonoDynamicTable *table;
2899         guint32 *values;
2900         guint32 token, mtoken = 0;
2901
2902         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2903         if (token)
2904                 return token;
2905
2906         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2907
2908         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2909         switch (mono_metadata_token_table (mtoken)) {
2910         case MONO_TABLE_MEMBERREF:
2911                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2912                 break;
2913         case MONO_TABLE_METHOD:
2914                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2915                 break;
2916         default:
2917                 g_assert_not_reached ();
2918         }
2919
2920         if (assembly->save) {
2921                 alloc_table (table, table->rows + 1);
2922                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2923                 values [MONO_METHODSPEC_METHOD] = mtoken;
2924                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2925         }
2926
2927         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2928         table->next_idx ++;
2929
2930         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2931         return token;
2932 }
2933
2934 static guint32
2935 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2936 {
2937         guint32 token;
2938
2939         if (mb->generic_params && create_methodspec) 
2940                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2941
2942         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2943         if (token)
2944                 return token;
2945
2946         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2947         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2948         return token;
2949 }
2950
2951 static guint32
2952 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2953 {
2954         guint32 token, parent, sig;
2955         ReflectionMethodBuilder rmb;
2956         char *name;
2957         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2958         
2959         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2960         if (token)
2961                 return token;
2962
2963         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2964
2965         if (tb->generic_params)
2966                 parent = create_generic_typespec (assembly, tb);
2967         else
2968                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2969         
2970         name = mono_string_to_utf8 (rmb.name);
2971         sig = method_builder_encode_signature (assembly, &rmb);
2972
2973         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2974
2975         g_free (name);
2976         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2977         return token;
2978 }
2979 #endif
2980
2981 static gboolean
2982 is_field_on_inst (MonoClassField *field)
2983 {
2984         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2985 }
2986
2987 /*
2988  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2989  */
2990 static MonoType*
2991 get_field_on_inst_generic_type (MonoClassField *field)
2992 {
2993         MonoClass *klass, *gtd;
2994         MonoDynamicGenericClass *dgclass;
2995         int field_index;
2996
2997         g_assert (is_field_on_inst (field));
2998
2999         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3000
3001         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3002                 field_index = field - dgclass->fields;
3003                 return dgclass->field_generic_types [field_index];              
3004         }
3005
3006         klass = field->parent;
3007         gtd = klass->generic_class->container_class;
3008
3009         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3010                 field_index = field - klass->fields;
3011                 return gtd->fields [field_index].type;
3012         }
3013
3014         g_assert_not_reached ();
3015         return 0;
3016 }
3017
3018 #ifndef DISABLE_REFLECTION_EMIT
3019 static guint32
3020 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3021 {
3022         MonoType *type;
3023         guint32 token;
3024
3025         g_assert (field);
3026         g_assert (field->parent);
3027
3028         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3029         if (token)
3030                 return token;
3031
3032         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3033                 int index = field - field->parent->fields;
3034                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3035         } else {
3036                 if (is_field_on_inst (field))
3037                         type = get_field_on_inst_generic_type (field);
3038                 else
3039                         type = mono_field_get_type (field);
3040         }
3041         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3042                                                                                         mono_field_get_name (field),
3043                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3044         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3045         return token;
3046 }
3047
3048 static guint32
3049 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3050 {
3051         guint32 token;
3052         MonoClass *klass;
3053         MonoGenericClass *gclass;
3054         MonoType *type;
3055         char *name;
3056
3057         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3058         if (token)
3059                 return token;
3060         if (is_sre_field_builder (mono_object_class (f->fb))) {
3061                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3062                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3063                 klass = mono_class_from_mono_type (type);
3064                 gclass = type->data.generic_class;
3065                 g_assert (gclass->is_dynamic);
3066
3067                 name = mono_string_to_utf8 (fb->name);
3068                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3069                                                                                                 field_encode_signature (assembly, fb));
3070                 g_free (name);          
3071         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3072                 guint32 sig;
3073                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3074
3075                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3076                 klass = mono_class_from_mono_type (type);
3077
3078                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3079                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3080         } else {
3081                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3082                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3083         }
3084
3085         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3086         return token;
3087 }
3088
3089 static guint32
3090 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3091 {
3092         guint32 sig, token;
3093         MonoClass *klass;
3094         MonoGenericClass *gclass;
3095         MonoType *type;
3096
3097         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3098
3099         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3100         if (token)
3101                 return token;
3102
3103         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3104                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3105                 ReflectionMethodBuilder rmb;
3106                 char *name;
3107
3108                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3109                 klass = mono_class_from_mono_type (type);
3110
3111                 gclass = type->data.generic_class;
3112                 g_assert (gclass->is_dynamic);
3113
3114                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3115
3116                 name = mono_string_to_utf8 (rmb.name);
3117
3118                 sig = method_builder_encode_signature (assembly, &rmb);
3119
3120                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3121                 g_free (name);
3122         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3123                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3124
3125                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3126                 klass = mono_class_from_mono_type (type);
3127
3128                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3129                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3130         } else {
3131                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3132                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3133         }
3134
3135
3136         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3137         return token;
3138 }
3139
3140 static MonoMethod*
3141 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3142 {
3143         MonoError error;
3144         MonoClass *klass;
3145         MonoGenericContext tmp_context;
3146         MonoType **type_argv;
3147         MonoGenericInst *ginst;
3148         MonoMethod *method, *inflated;
3149         int count, i;
3150
3151         init_type_builder_generics ((MonoObject*)m->inst);
3152
3153         method = inflate_method (m->inst, (MonoObject*)m->mb);
3154
3155         klass = method->klass;
3156
3157         if (m->method_args == NULL)
3158                 return method;
3159
3160         if (method->is_inflated)
3161                 method = ((MonoMethodInflated *) method)->declaring;
3162
3163         count = mono_array_length (m->method_args);
3164
3165         type_argv = g_new0 (MonoType *, count);
3166         for (i = 0; i < count; i++) {
3167                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3168                 type_argv [i] = mono_reflection_type_get_handle (garg);
3169         }
3170         ginst = mono_metadata_get_generic_inst (count, type_argv);
3171         g_free (type_argv);
3172
3173         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3174         tmp_context.method_inst = ginst;
3175
3176         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3177         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3178         return inflated;
3179 }
3180
3181 static guint32
3182 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3183 {
3184         guint32 sig, token = 0;
3185         MonoType *type;
3186         MonoClass *klass;
3187
3188         if (m->method_args) {
3189                 MonoMethod *inflated;
3190
3191                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3192                 if (create_methodspec)
3193                         token = mono_image_get_methodspec_token (assembly, inflated);
3194                 else
3195                         token = mono_image_get_inflated_method_token (assembly, inflated);
3196                 return token;
3197         }
3198
3199         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3200         if (token)
3201                 return token;
3202
3203         if (is_sre_method_builder (mono_object_class (m->mb))) {
3204                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3205                 MonoGenericClass *gclass;
3206                 ReflectionMethodBuilder rmb;
3207                 char *name;
3208
3209                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3210                 klass = mono_class_from_mono_type (type);
3211                 gclass = type->data.generic_class;
3212                 g_assert (gclass->is_dynamic);
3213
3214                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3215
3216                 name = mono_string_to_utf8 (rmb.name);
3217
3218                 sig = method_builder_encode_signature (assembly, &rmb);
3219
3220                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3221                 g_free (name);          
3222         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3223                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3224
3225                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3226                 klass = mono_class_from_mono_type (type);
3227
3228                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3229                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3230         } else {
3231                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3232                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3233         }
3234
3235         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3236         return token;
3237 }
3238
3239 static guint32
3240 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3241 {
3242         SigBuffer buf;
3243         int i;
3244         guint32 nparams = context->method_inst->type_argc;
3245         guint32 idx;
3246
3247         if (!assembly->save)
3248                 return 0;
3249
3250         sigbuffer_init (&buf, 32);
3251         /*
3252          * FIXME: vararg, explicit_this, differenc call_conv values...
3253          */
3254         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3255         sigbuffer_add_value (&buf, nparams);
3256
3257         for (i = 0; i < nparams; i++)
3258                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3259
3260         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3261         sigbuffer_free (&buf);
3262         return idx;
3263 }
3264
3265 static guint32
3266 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3267 {
3268         MonoDynamicTable *table;
3269         guint32 *values;
3270         guint32 token, mtoken = 0, sig;
3271         MonoMethodInflated *imethod;
3272         MonoMethod *declaring;
3273
3274         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3275
3276         g_assert (method->is_inflated);
3277         imethod = (MonoMethodInflated *) method;
3278         declaring = imethod->declaring;
3279
3280         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3281         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3282
3283         if (!mono_method_signature (declaring)->generic_param_count)
3284                 return mtoken;
3285
3286         switch (mono_metadata_token_table (mtoken)) {
3287         case MONO_TABLE_MEMBERREF:
3288                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3289                 break;
3290         case MONO_TABLE_METHOD:
3291                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3292                 break;
3293         default:
3294                 g_assert_not_reached ();
3295         }
3296
3297         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3298
3299         if (assembly->save) {
3300                 alloc_table (table, table->rows + 1);
3301                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3302                 values [MONO_METHODSPEC_METHOD] = mtoken;
3303                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3304         }
3305
3306         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3307         table->next_idx ++;
3308
3309         return token;
3310 }
3311
3312 static guint32
3313 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3314 {
3315         MonoMethodInflated *imethod;
3316         guint32 token;
3317         
3318         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3319         if (token)
3320                 return token;
3321
3322         g_assert (method->is_inflated);
3323         imethod = (MonoMethodInflated *) method;
3324
3325         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3326                 token = method_encode_methodspec (assembly, method);
3327         } else {
3328                 guint32 sig = method_encode_signature (
3329                         assembly, mono_method_signature (imethod->declaring));
3330                 token = mono_image_get_memberref_token (
3331                         assembly, &method->klass->byval_arg, method->name, sig);
3332         }
3333
3334         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3335         return token;
3336 }
3337
3338 static guint32
3339 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3340 {
3341         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3342         guint32 sig, token;
3343
3344         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3345         token = mono_image_get_memberref_token (
3346                 assembly, &m->klass->byval_arg, m->name, sig);
3347
3348         return token;
3349 }
3350
3351 static guint32
3352 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3353 {
3354         MonoDynamicTable *table;
3355         MonoClass *klass;
3356         MonoType *type;
3357         guint32 *values;
3358         guint32 token;
3359         SigBuffer buf;
3360         int count, i;
3361
3362         /*
3363          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3364          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3365          * Because of this, we must not insert it into the `typeref' hash table.
3366          */
3367         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3368         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3369         if (token)
3370                 return token;
3371
3372         sigbuffer_init (&buf, 32);
3373
3374         g_assert (tb->generic_params);
3375         klass = mono_class_from_mono_type (type);
3376
3377         if (tb->generic_container)
3378                 mono_reflection_create_generic_class (tb);
3379
3380         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3381         g_assert (klass->generic_container);
3382         sigbuffer_add_value (&buf, klass->byval_arg.type);
3383         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3384
3385         count = mono_array_length (tb->generic_params);
3386         sigbuffer_add_value (&buf, count);
3387         for (i = 0; i < count; i++) {
3388                 MonoReflectionGenericParam *gparam;
3389
3390                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3391
3392                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3393         }
3394
3395         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3396
3397         if (assembly->save) {
3398                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3399                 alloc_table (table, table->rows + 1);
3400                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3401                 values [MONO_TYPESPEC_SIGNATURE] = token;
3402         }
3403         sigbuffer_free (&buf);
3404
3405         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3406         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3407         table->next_idx ++;
3408         return token;
3409 }
3410
3411 /*
3412  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3413  */
3414 static MonoType*
3415 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3416 {
3417         int i, count, len, pos;
3418         MonoType *t;
3419
3420         count = 0;
3421         if (modreq)
3422                 count += mono_array_length (modreq);
3423         if (modopt)
3424                 count += mono_array_length (modopt);
3425
3426         if (count == 0)
3427                 return mono_metadata_type_dup (NULL, type);
3428
3429         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3430         t = (MonoType *)g_malloc (len);
3431         memcpy (t, type, MONO_SIZEOF_TYPE);
3432
3433         t->num_mods = count;
3434         pos = 0;
3435         if (modreq) {
3436                 for (i = 0; i < mono_array_length (modreq); ++i) {
3437                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3438                         t->modifiers [pos].required = 1;
3439                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3440                         pos ++;
3441                 }
3442         }
3443         if (modopt) {
3444                 for (i = 0; i < mono_array_length (modopt); ++i) {
3445                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3446                         t->modifiers [pos].required = 0;
3447                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3448                         pos ++;
3449                 }
3450         }
3451
3452         return t;
3453 }
3454
3455 static void
3456 init_type_builder_generics (MonoObject *type)
3457 {
3458         MonoReflectionTypeBuilder *tb;
3459
3460         if (!is_sre_type_builder(mono_object_class (type)))
3461                 return;
3462         tb = (MonoReflectionTypeBuilder *)type;
3463
3464         if (tb && tb->generic_container)
3465                 mono_reflection_create_generic_class (tb);
3466 }
3467
3468 static guint32
3469 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3470 {
3471         MonoDynamicTable *table;
3472         MonoType *custom = NULL, *type;
3473         guint32 *values;
3474         guint32 token, pclass, parent, sig;
3475         gchar *name;
3476
3477         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3478         if (token)
3479                 return token;
3480
3481         /* FIXME: is this call necessary? */
3482         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3483         name = mono_string_to_utf8 (fb->name);
3484
3485         /*FIXME this is one more layer of ugliness due how types are created.*/
3486         init_type_builder_generics (fb->type);
3487
3488         /* fb->type does not include the custom modifiers */
3489         /* FIXME: We should do this in one place when a fieldbuilder is created */
3490         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3491         if (fb->modreq || fb->modopt)
3492                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3493
3494         sig = fieldref_encode_signature (assembly, NULL, type);
3495         g_free (custom);
3496
3497         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3498         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3499         
3500         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3501         parent >>= MONO_TYPEDEFORREF_BITS;
3502
3503         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3504
3505         if (assembly->save) {
3506                 alloc_table (table, table->rows + 1);
3507                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3508                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3509                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3510                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3511         }
3512
3513         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3514         table->next_idx ++;
3515         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3516         g_free (name);
3517         return token;
3518 }
3519
3520 static guint32
3521 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3522 {
3523         SigBuffer buf;
3524         guint32 nargs;
3525         guint32 i, idx;
3526
3527         if (!assembly->save)
3528                 return 0;
3529
3530         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3531         g_assert (helper->type == 2);
3532
3533         if (helper->arguments)
3534                 nargs = mono_array_length (helper->arguments);
3535         else
3536                 nargs = 0;
3537
3538         sigbuffer_init (&buf, 32);
3539
3540         /* Encode calling convention */
3541         /* Change Any to Standard */
3542         if ((helper->call_conv & 0x03) == 0x03)
3543                 helper->call_conv = 0x01;
3544         /* explicit_this implies has_this */
3545         if (helper->call_conv & 0x40)
3546                 helper->call_conv &= 0x20;
3547
3548         if (helper->call_conv == 0) { /* Unmanaged */
3549                 idx = helper->unmanaged_call_conv - 1;
3550         } else {
3551                 /* Managed */
3552                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3553                 if (helper->call_conv & 0x02) /* varargs */
3554                         idx += 0x05;
3555         }
3556
3557         sigbuffer_add_byte (&buf, idx);
3558         sigbuffer_add_value (&buf, nargs);
3559         encode_reflection_type (assembly, helper->return_type, &buf);
3560         for (i = 0; i < nargs; ++i) {
3561                 MonoArray *modreqs = NULL;
3562                 MonoArray *modopts = NULL;
3563                 MonoReflectionType *pt;
3564
3565                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3566                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3567                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3568                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3569
3570                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3571                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3572                 encode_reflection_type (assembly, pt, &buf);
3573         }
3574         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3575         sigbuffer_free (&buf);
3576
3577         return idx;
3578 }
3579
3580 static guint32 
3581 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3582 {
3583         guint32 idx;
3584         MonoDynamicTable *table;
3585         guint32 *values;
3586
3587         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3588         idx = table->next_idx ++;
3589         table->rows ++;
3590         alloc_table (table, table->rows);
3591         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3592
3593         values [MONO_STAND_ALONE_SIGNATURE] =
3594                 mono_reflection_encode_sighelper (assembly, helper);
3595
3596         return idx;
3597 }
3598
3599 static int
3600 reflection_cc_to_file (int call_conv) {
3601         switch (call_conv & 0x3) {
3602         case 0:
3603         case 1: return MONO_CALL_DEFAULT;
3604         case 2: return MONO_CALL_VARARG;
3605         default:
3606                 g_assert_not_reached ();
3607         }
3608         return 0;
3609 }
3610 #endif /* !DISABLE_REFLECTION_EMIT */
3611
3612 typedef struct {
3613         MonoType *parent;
3614         MonoMethodSignature *sig;
3615         char *name;
3616         guint32 token;
3617 } ArrayMethod;
3618
3619 #ifndef DISABLE_REFLECTION_EMIT
3620 static guint32
3621 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3622 {
3623         guint32 nparams, i;
3624         GList *tmp;
3625         char *name;
3626         MonoMethodSignature *sig;
3627         ArrayMethod *am;
3628         MonoType *mtype;
3629
3630         name = mono_string_to_utf8 (m->name);
3631         nparams = mono_array_length (m->parameters);
3632         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3633         sig->hasthis = 1;
3634         sig->sentinelpos = -1;
3635         sig->call_convention = reflection_cc_to_file (m->call_conv);
3636         sig->param_count = nparams;
3637         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3638         mtype = mono_reflection_type_get_handle (m->parent);
3639         for (i = 0; i < nparams; ++i)
3640                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3641
3642         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3643                 am = (ArrayMethod *)tmp->data;
3644                 if (strcmp (name, am->name) == 0 && 
3645                                 mono_metadata_type_equal (am->parent, mtype) &&
3646                                 mono_metadata_signature_equal (am->sig, sig)) {
3647                         g_free (name);
3648                         g_free (sig);
3649                         m->table_idx = am->token & 0xffffff;
3650                         return am->token;
3651                 }
3652         }
3653         am = g_new0 (ArrayMethod, 1);
3654         am->name = name;
3655         am->sig = sig;
3656         am->parent = mtype;
3657         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3658                 method_encode_signature (assembly, sig));
3659         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3660         m->table_idx = am->token & 0xffffff;
3661         return am->token;
3662 }
3663
3664 /*
3665  * Insert into the metadata tables all the info about the TypeBuilder tb.
3666  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3667  */
3668 static void
3669 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3670 {
3671         MonoError error;
3672         MonoDynamicTable *table;
3673         guint *values;
3674         int i, is_object = 0, is_system = 0;
3675         char *n;
3676
3677         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3678         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3679         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3680         n = mono_string_to_utf8 (tb->name);
3681         if (strcmp (n, "Object") == 0)
3682                 is_object++;
3683         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3684         g_free (n);
3685         n = mono_string_to_utf8 (tb->nspace);
3686         if (strcmp (n, "System") == 0)
3687                 is_system++;
3688         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3689         g_free (n);
3690         if (tb->parent && !(is_system && is_object) && 
3691                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3692                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3693         } else {
3694                 values [MONO_TYPEDEF_EXTENDS] = 0;
3695         }
3696         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3697         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3698
3699         /*
3700          * if we have explicitlayout or sequentiallayouts, output data in the
3701          * ClassLayout table.
3702          */
3703         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3704                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3705                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3706                 table->rows++;
3707                 alloc_table (table, table->rows);
3708                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3709                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3710                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3711                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3712         }
3713
3714         /* handle interfaces */
3715         if (tb->interfaces) {
3716                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3717                 i = table->rows;
3718                 table->rows += mono_array_length (tb->interfaces);
3719                 alloc_table (table, table->rows);
3720                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3721                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3722                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3723                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3724                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3725                         values += MONO_INTERFACEIMPL_SIZE;
3726                 }
3727         }
3728
3729         /* handle fields */
3730         if (tb->fields) {
3731                 table = &assembly->tables [MONO_TABLE_FIELD];
3732                 table->rows += tb->num_fields;
3733                 alloc_table (table, table->rows);
3734                 for (i = 0; i < tb->num_fields; ++i)
3735                         mono_image_get_field_info (
3736                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3737         }
3738
3739         /* handle constructors */
3740         if (tb->ctors) {
3741                 table = &assembly->tables [MONO_TABLE_METHOD];
3742                 table->rows += mono_array_length (tb->ctors);
3743                 alloc_table (table, table->rows);
3744                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3745                         mono_image_get_ctor_info (domain,
3746                                                   mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3747                                                   assembly, &error);
3748                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3749                 }
3750         }
3751
3752         /* handle methods */
3753         if (tb->methods) {
3754                 table = &assembly->tables [MONO_TABLE_METHOD];
3755                 table->rows += tb->num_methods;
3756                 alloc_table (table, table->rows);
3757                 for (i = 0; i < tb->num_methods; ++i)
3758                         mono_image_get_method_info (
3759                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3760         }
3761
3762         /* Do the same with properties etc.. */
3763         if (tb->events && mono_array_length (tb->events)) {
3764                 table = &assembly->tables [MONO_TABLE_EVENT];
3765                 table->rows += mono_array_length (tb->events);
3766                 alloc_table (table, table->rows);
3767                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3768                 table->rows ++;
3769                 alloc_table (table, table->rows);
3770                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3771                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3772                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3773                 for (i = 0; i < mono_array_length (tb->events); ++i)
3774                         mono_image_get_event_info (
3775                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3776         }
3777         if (tb->properties && mono_array_length (tb->properties)) {
3778                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3779                 table->rows += mono_array_length (tb->properties);
3780                 alloc_table (table, table->rows);
3781                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3782                 table->rows ++;
3783                 alloc_table (table, table->rows);
3784                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3785                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3786                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3787                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3788                         mono_image_get_property_info (
3789                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3790         }
3791
3792         /* handle generic parameters */
3793         if (tb->generic_params) {
3794                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3795                 table->rows += mono_array_length (tb->generic_params);
3796                 alloc_table (table, table->rows);
3797                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3798                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3799
3800                         mono_image_get_generic_param_info (
3801                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3802                 }
3803         }
3804
3805         mono_image_add_decl_security (assembly, 
3806                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3807
3808         if (tb->subtypes) {
3809                 MonoDynamicTable *ntable;
3810                 
3811                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3812                 ntable->rows += mono_array_length (tb->subtypes);
3813                 alloc_table (ntable, ntable->rows);
3814                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3815
3816                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3817                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3818
3819                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3820                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3821                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3822                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3823                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3824                                 ntable->next_idx, ntable->rows);*/
3825                         values += MONO_NESTED_CLASS_SIZE;
3826                         ntable->next_idx++;
3827                 }
3828         }
3829 }
3830 #endif
3831
3832 static void
3833 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3834 {
3835         int i;
3836
3837         mono_ptr_array_append (*types, type);
3838
3839         if (!type->subtypes)
3840                 return;
3841
3842         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3843                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3844                 collect_types (types, subtype);
3845         }
3846 }
3847
3848 static gint
3849 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3850 {
3851         if ((*type1)->table_idx < (*type2)->table_idx)
3852                 return -1;
3853         else
3854                 if ((*type1)->table_idx > (*type2)->table_idx)
3855                         return 1;
3856         else
3857                 return 0;
3858 }
3859
3860 static gboolean
3861 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3862         int i;
3863
3864         mono_error_init (error);
3865         if (!pinfo)
3866                 return TRUE;
3867         for (i = 0; i < mono_array_length (pinfo); ++i) {
3868                 MonoReflectionParamBuilder *pb;
3869                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3870                 if (!pb)
3871                         continue;
3872                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3873                         return FALSE;
3874         }
3875
3876         return TRUE;
3877 }
3878
3879 static gboolean
3880 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3881         int i;
3882
3883         mono_error_init (error);
3884         
3885         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3886                 return FALSE;
3887         if (tb->fields) {
3888                 for (i = 0; i < tb->num_fields; ++i) {
3889                         MonoReflectionFieldBuilder* fb;
3890                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3891                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3892                                 return FALSE;
3893                 }
3894         }
3895         if (tb->events) {
3896                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3897                         MonoReflectionEventBuilder* eb;
3898                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3899                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3900                                 return FALSE;
3901                 }
3902         }
3903         if (tb->properties) {
3904                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3905                         MonoReflectionPropertyBuilder* pb;
3906                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3907                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3908                                 return FALSE;
3909                 }
3910         }
3911         if (tb->ctors) {
3912                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3913                         MonoReflectionCtorBuilder* cb;
3914                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3915                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3916                             !params_add_cattrs (assembly, cb->pinfo, error))
3917                                 return FALSE;
3918                 }
3919         }
3920
3921         if (tb->methods) {
3922                 for (i = 0; i < tb->num_methods; ++i) {
3923                         MonoReflectionMethodBuilder* mb;
3924                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3925                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3926                             !params_add_cattrs (assembly, mb->pinfo, error))
3927                                 return FALSE;
3928                 }
3929         }
3930
3931         if (tb->subtypes) {
3932                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3933                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3934                                 return FALSE;
3935                 }
3936         }
3937
3938         return TRUE;
3939 }
3940
3941 static gboolean
3942 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3943 {
3944         int i;
3945         
3946         mono_error_init (error);
3947
3948         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3949                 return FALSE;
3950
3951         if (moduleb->global_methods) {
3952                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3953                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3954                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3955                             !params_add_cattrs (assembly, mb->pinfo, error))
3956                                 return FALSE;
3957                 }
3958         }
3959
3960         if (moduleb->global_fields) {
3961                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3962                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3963                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3964                                 return FALSE;
3965                 }
3966         }
3967         
3968         if (moduleb->types) {
3969                 for (i = 0; i < moduleb->num_types; ++i) {
3970                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
3971                                 return FALSE;
3972                 }
3973         }
3974
3975         return TRUE;
3976 }
3977
3978 static void
3979 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3980 {
3981         MonoDynamicTable *table;
3982         guint32 *values;
3983         char blob_size [6];
3984         guchar hash [20];
3985         char *b = blob_size;
3986         char *dir, *path;
3987
3988         table = &assembly->tables [MONO_TABLE_FILE];
3989         table->rows++;
3990         alloc_table (table, table->rows);
3991         values = table->values + table->next_idx * MONO_FILE_SIZE;
3992         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3993         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3994         if (image_is_dynamic (module->image)) {
3995                 /* This depends on the fact that the main module is emitted last */
3996                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3997                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3998         } else {
3999                 dir = NULL;
4000                 path = g_strdup (module->image->name);
4001         }
4002         mono_sha1_get_digest_from_file (path, hash);
4003         g_free (dir);
4004         g_free (path);
4005         mono_metadata_encode_value (20, b, &b);
4006         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4007         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4008         table->next_idx ++;
4009 }
4010
4011 static void
4012 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4013 {
4014         MonoDynamicTable *table;
4015         int i;
4016
4017         table = &assembly->tables [MONO_TABLE_MODULE];
4018         mb->table_idx = table->next_idx ++;
4019         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4020         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4021         i /= 16;
4022         ++i;
4023         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4024         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4025         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4026         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4027 }
4028
4029 static guint32
4030 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4031         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4032 {
4033         MonoDynamicTable *table;
4034         guint32 *values;
4035         guint32 visib, res;
4036
4037         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4038         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4039                 return 0;
4040
4041         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4042         table->rows++;
4043         alloc_table (table, table->rows);
4044         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4045
4046         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4047         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4048         if (klass->nested_in)
4049                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4050         else
4051                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4052         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4053         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4054
4055         res = table->next_idx;
4056
4057         table->next_idx ++;
4058
4059         /* Emit nested types */
4060         if (klass->ext && klass->ext->nested_classes) {
4061                 GList *tmp;
4062
4063                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4064                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4065         }
4066
4067         return res;
4068 }
4069
4070 static void
4071 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4072         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4073 {
4074         MonoClass *klass;
4075         guint32 idx, i;
4076
4077         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4078
4079         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4080
4081         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4082                                                                                                    parent_index, assembly);
4083
4084         /* 
4085          * Emit nested types
4086          * We need to do this ourselves since klass->nested_classes is not set up.
4087          */
4088         if (tb->subtypes) {
4089                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4090                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4091         }
4092 }
4093
4094 static void
4095 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4096         guint32 module_index, MonoDynamicImage *assembly)
4097 {
4098         MonoImage *image = module->image;
4099         MonoTableInfo  *t;
4100         guint32 i;
4101
4102         t = &image->tables [MONO_TABLE_TYPEDEF];
4103
4104         for (i = 0; i < t->rows; ++i) {
4105                 MonoError error;
4106                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4107                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4108
4109                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4110                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4111         }
4112 }
4113
4114 static void
4115 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4116 {
4117         MonoDynamicTable *table;
4118         guint32 *values;
4119         guint32 scope, scope_idx, impl, current_idx;
4120         gboolean forwarder = TRUE;
4121         gpointer iter = NULL;
4122         MonoClass *nested;
4123
4124         if (klass->nested_in) {
4125                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4126                 forwarder = FALSE;
4127         } else {
4128                 scope = resolution_scope_from_image (assembly, klass->image);
4129                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4130                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4131                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4132         }
4133
4134         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4135
4136         table->rows++;
4137         alloc_table (table, table->rows);
4138         current_idx = table->next_idx;
4139         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4140
4141         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4142         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4143         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4144         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4145         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4146
4147         table->next_idx++;
4148
4149         while ((nested = mono_class_get_nested_types (klass, &iter)))
4150                 add_exported_type (assemblyb, assembly, nested, current_idx);
4151 }
4152
4153 static void
4154 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4155 {
4156         MonoClass *klass;
4157         int i;
4158
4159         if (!assemblyb->type_forwarders)
4160                 return;
4161
4162         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4163                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4164                 MonoType *type;
4165                 if (!t)
4166                         continue;
4167
4168                 type = mono_reflection_type_get_handle (t);
4169                 g_assert (type);
4170
4171                 klass = mono_class_from_mono_type (type);
4172
4173                 add_exported_type (assemblyb, assembly, klass, 0);
4174         }
4175 }
4176
4177 #define align_pointer(base,p)\
4178         do {\
4179                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4180                 if (__diff & 3)\
4181                         (p) += 4 - (__diff & 3);\
4182         } while (0)
4183
4184 static int
4185 compare_constants (const void *a, const void *b)
4186 {
4187         const guint32 *a_values = (const guint32 *)a;
4188         const guint32 *b_values = (const guint32 *)b;
4189         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4190 }
4191
4192 static int
4193 compare_semantics (const void *a, const void *b)
4194 {
4195         const guint32 *a_values = (const guint32 *)a;
4196         const guint32 *b_values = (const guint32 *)b;
4197         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4198         if (assoc)
4199                 return assoc;
4200         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4201 }
4202
4203 static int
4204 compare_custom_attrs (const void *a, const void *b)
4205 {
4206         const guint32 *a_values = (const guint32 *)a;
4207         const guint32 *b_values = (const guint32 *)b;
4208
4209         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4210 }
4211
4212 static int
4213 compare_field_marshal (const void *a, const void *b)
4214 {
4215         const guint32 *a_values = (const guint32 *)a;
4216         const guint32 *b_values = (const guint32 *)b;
4217
4218         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4219 }
4220
4221 static int
4222 compare_nested (const void *a, const void *b)
4223 {
4224         const guint32 *a_values = (const guint32 *)a;
4225         const guint32 *b_values = (const guint32 *)b;
4226
4227         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4228 }
4229
4230 static int
4231 compare_genericparam (const void *a, const void *b)
4232 {
4233         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4234         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4235
4236         if ((*b_entry)->owner == (*a_entry)->owner)
4237                 return 
4238                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4239                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4240         else
4241                 return (*a_entry)->owner - (*b_entry)->owner;
4242 }
4243
4244 static int
4245 compare_declsecurity_attrs (const void *a, const void *b)
4246 {
4247         const guint32 *a_values = (const guint32 *)a;
4248         const guint32 *b_values = (const guint32 *)b;
4249
4250         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4251 }
4252
4253 static int
4254 compare_interface_impl (const void *a, const void *b)
4255 {
4256         const guint32 *a_values = (const guint32 *)a;
4257         const guint32 *b_values = (const guint32 *)b;
4258
4259         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4260         if (klass)
4261                 return klass;
4262
4263         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4264 }
4265
4266 static void
4267 pad_heap (MonoDynamicStream *sh)
4268 {
4269         if (sh->index & 3) {
4270                 int sz = 4 - (sh->index & 3);
4271                 memset (sh->data + sh->index, 0, sz);
4272                 sh->index += sz;
4273         }
4274 }
4275
4276 struct StreamDesc {
4277         const char *name;
4278         MonoDynamicStream *stream;
4279 };
4280
4281 /*
4282  * build_compressed_metadata() fills in the blob of data that represents the 
4283  * raw metadata as it will be saved in the PE file. The five streams are output 
4284  * and the metadata tables are comnpressed from the guint32 array representation, 
4285  * to the compressed on-disk format.
4286  */
4287 static void
4288 build_compressed_metadata (MonoDynamicImage *assembly)
4289 {
4290         MonoDynamicTable *table;
4291         int i;
4292         guint64 valid_mask = 0;
4293         guint64 sorted_mask;
4294         guint32 heapt_size = 0;
4295         guint32 meta_size = 256; /* allow for header and other stuff */
4296         guint32 table_offset;
4297         guint32 ntables = 0;
4298         guint64 *int64val;
4299         guint32 *int32val;
4300         guint16 *int16val;
4301         MonoImage *meta;
4302         unsigned char *p;
4303         struct StreamDesc stream_desc [5];
4304
4305         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4306         for (i = 0; i < assembly->gen_params->len; i++){
4307                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4308                 write_generic_param_entry (assembly, entry);
4309         }
4310
4311         stream_desc [0].name  = "#~";
4312         stream_desc [0].stream = &assembly->tstream;
4313         stream_desc [1].name  = "#Strings";
4314         stream_desc [1].stream = &assembly->sheap;
4315         stream_desc [2].name  = "#US";
4316         stream_desc [2].stream = &assembly->us;
4317         stream_desc [3].name  = "#Blob";
4318         stream_desc [3].stream = &assembly->blob;
4319         stream_desc [4].name  = "#GUID";
4320         stream_desc [4].stream = &assembly->guid;
4321         
4322         /* tables that are sorted */
4323         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4324                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4325                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4326                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4327                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4328                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4329                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4330         
4331         /* Compute table sizes */
4332         /* the MonoImage has already been created in mono_image_basic_init() */
4333         meta = &assembly->image;
4334
4335         /* sizes should be multiple of 4 */
4336         pad_heap (&assembly->blob);
4337         pad_heap (&assembly->guid);
4338         pad_heap (&assembly->sheap);
4339         pad_heap (&assembly->us);
4340
4341         /* Setup the info used by compute_sizes () */
4342         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4343         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4344         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4345
4346         meta_size += assembly->blob.index;
4347         meta_size += assembly->guid.index;
4348         meta_size += assembly->sheap.index;
4349         meta_size += assembly->us.index;
4350
4351         for (i=0; i < MONO_TABLE_NUM; ++i)
4352                 meta->tables [i].rows = assembly->tables [i].rows;
4353         
4354         for (i = 0; i < MONO_TABLE_NUM; i++){
4355                 if (meta->tables [i].rows == 0)
4356                         continue;
4357                 valid_mask |= (guint64)1 << i;
4358                 ntables ++;
4359                 meta->tables [i].row_size = mono_metadata_compute_size (
4360                         meta, i, &meta->tables [i].size_bitfield);
4361                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4362         }
4363         heapt_size += 24; /* #~ header size */
4364         heapt_size += ntables * 4;
4365         /* make multiple of 4 */
4366         heapt_size += 3;
4367         heapt_size &= ~3;
4368         meta_size += heapt_size;
4369         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4370         p = (unsigned char*)meta->raw_metadata;
4371         /* the metadata signature */
4372         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4373         /* version numbers and 4 bytes reserved */
4374         int16val = (guint16*)p;
4375         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4376         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4377         p += 8;
4378         /* version string */
4379         int32val = (guint32*)p;
4380         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4381         p += 4;
4382         memcpy (p, meta->version, strlen (meta->version));
4383         p += GUINT32_FROM_LE (*int32val);
4384         align_pointer (meta->raw_metadata, p);
4385         int16val = (guint16*)p;
4386         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4387         *int16val = GUINT16_TO_LE (5); /* number of streams */
4388         p += 4;
4389
4390         /*
4391          * write the stream info.
4392          */
4393         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4394         table_offset += 3; table_offset &= ~3;
4395
4396         assembly->tstream.index = heapt_size;
4397         for (i = 0; i < 5; ++i) {
4398                 int32val = (guint32*)p;
4399                 stream_desc [i].stream->offset = table_offset;
4400                 *int32val++ = GUINT32_TO_LE (table_offset);
4401                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4402                 table_offset += GUINT32_FROM_LE (*int32val);
4403                 table_offset += 3; table_offset &= ~3;
4404                 p += 8;
4405                 strcpy ((char*)p, stream_desc [i].name);
4406                 p += strlen (stream_desc [i].name) + 1;
4407                 align_pointer (meta->raw_metadata, p);
4408         }
4409         /* 
4410          * now copy the data, the table stream header and contents goes first.
4411          */
4412         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4413         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4414         int32val = (guint32*)p;
4415         *int32val = GUINT32_TO_LE (0); /* reserved */
4416         p += 4;
4417
4418         *p++ = 2; /* version */
4419         *p++ = 0;
4420
4421         if (meta->idx_string_wide)
4422                 *p |= 0x01;
4423         if (meta->idx_guid_wide)
4424                 *p |= 0x02;
4425         if (meta->idx_blob_wide)
4426                 *p |= 0x04;
4427         ++p;
4428         *p++ = 1; /* reserved */
4429         int64val = (guint64*)p;
4430         *int64val++ = GUINT64_TO_LE (valid_mask);
4431         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4432         p += 16;
4433         int32val = (guint32*)p;
4434         for (i = 0; i < MONO_TABLE_NUM; i++){
4435                 if (meta->tables [i].rows == 0)
4436                         continue;
4437                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4438         }
4439         p = (unsigned char*)int32val;
4440
4441         /* sort the tables that still need sorting */
4442         table = &assembly->tables [MONO_TABLE_CONSTANT];
4443         if (table->rows)
4444                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4445         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4446         if (table->rows)
4447                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4448         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4449         if (table->rows)
4450                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4451         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4452         if (table->rows)
4453                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4454         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4455         if (table->rows)
4456                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4457         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4458         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4459         if (table->rows)
4460                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4461         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4462         if (table->rows)
4463                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4464
4465         /* compress the tables */
4466         for (i = 0; i < MONO_TABLE_NUM; i++){
4467                 int row, col;
4468                 guint32 *values;
4469                 guint32 bitfield = meta->tables [i].size_bitfield;
4470                 if (!meta->tables [i].rows)
4471                         continue;
4472                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4473                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4474                 meta->tables [i].base = (char*)p;
4475                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4476                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4477                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4478                                 switch (mono_metadata_table_size (bitfield, col)) {
4479                                 case 1:
4480                                         *p++ = values [col];
4481                                         break;
4482                                 case 2:
4483                                         *p++ = values [col] & 0xff;
4484                                         *p++ = (values [col] >> 8) & 0xff;
4485                                         break;
4486                                 case 4:
4487                                         *p++ = values [col] & 0xff;
4488                                         *p++ = (values [col] >> 8) & 0xff;
4489                                         *p++ = (values [col] >> 16) & 0xff;
4490                                         *p++ = (values [col] >> 24) & 0xff;
4491                                         break;
4492                                 default:
4493                                         g_assert_not_reached ();
4494                                 }
4495                         }
4496                 }
4497                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4498         }
4499         
4500         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4501         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4502         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4503         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4504         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4505
4506         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4507 }
4508
4509 /*
4510  * Some tables in metadata need to be sorted according to some criteria, but
4511  * when methods and fields are first created with reflection, they may be assigned a token
4512  * that doesn't correspond to the final token they will get assigned after the sorting.
4513  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4514  * with the reflection objects that represent them. Once all the tables are set up, the 
4515  * reflection objects will contains the correct table index. fixup_method() will fixup the
4516  * tokens for the method with ILGenerator @ilgen.
4517  */
4518 static void
4519 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4520 {
4521         guint32 code_idx = GPOINTER_TO_UINT (value);
4522         MonoReflectionILTokenInfo *iltoken;
4523         MonoReflectionFieldBuilder *field;
4524         MonoReflectionCtorBuilder *ctor;
4525         MonoReflectionMethodBuilder *method;
4526         MonoReflectionTypeBuilder *tb;
4527         MonoReflectionArrayMethod *am;
4528         guint32 i, idx = 0;
4529         unsigned char *target;
4530
4531         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4532                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4533                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4534                 switch (target [3]) {
4535                 case MONO_TABLE_FIELD:
4536                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4537                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4538                                 idx = field->table_idx;
4539                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4540                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4541                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4542                         } else {
4543                                 g_assert_not_reached ();
4544                         }
4545                         break;
4546                 case MONO_TABLE_METHOD:
4547                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4548                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4549                                 idx = method->table_idx;
4550                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4551                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4552                                 idx = ctor->table_idx;
4553                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4554                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4555                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4556                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4557                         } else {
4558                                 g_assert_not_reached ();
4559                         }
4560                         break;
4561                 case MONO_TABLE_TYPEDEF:
4562                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4563                                 g_assert_not_reached ();
4564                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4565                         idx = tb->table_idx;
4566                         break;
4567                 case MONO_TABLE_MEMBERREF:
4568                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4569                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4570                                 idx = am->table_idx;
4571                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4572                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4573                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4574                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4575                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4576                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4577                                 continue;
4578                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4579                                 continue;
4580                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4581                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4582                                 g_assert (is_field_on_inst (f));
4583                                 continue;
4584                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4585                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4586                                 continue;
4587                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4588                                 continue;
4589                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4590                                 continue;
4591                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4592                                 continue;
4593                         } else {
4594                                 g_assert_not_reached ();
4595                         }
4596                         break;
4597                 case MONO_TABLE_METHODSPEC:
4598                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4599                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4600                                 g_assert (mono_method_signature (m)->generic_param_count);
4601                                 continue;
4602                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4603                                 continue;
4604                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4605                                 continue;
4606                         } else {
4607                                 g_assert_not_reached ();
4608                         }
4609                         break;
4610                 default:
4611                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4612                 }
4613                 target [0] = idx & 0xff;
4614                 target [1] = (idx >> 8) & 0xff;
4615                 target [2] = (idx >> 16) & 0xff;
4616         }
4617 }
4618
4619 /*
4620  * fixup_cattrs:
4621  *
4622  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4623  * value is not known when the table is emitted.
4624  */
4625 static void
4626 fixup_cattrs (MonoDynamicImage *assembly)
4627 {
4628         MonoDynamicTable *table;
4629         guint32 *values;
4630         guint32 type, i, idx, token;
4631         MonoObject *ctor;
4632
4633         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4634
4635         for (i = 0; i < table->rows; ++i) {
4636                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4637
4638                 type = values [MONO_CUSTOM_ATTR_TYPE];
4639                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4640                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4641                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4642                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4643                         g_assert (ctor);
4644
4645                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4646                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4647                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4648                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4649                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4650                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4651                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4652                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4653                         }
4654                 }
4655         }
4656 }
4657
4658 static void
4659 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4660 {
4661         MonoDynamicTable *table;
4662         guint32 *values;
4663
4664         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4665         table->rows++;
4666         alloc_table (table, table->rows);
4667         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4668         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4669         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4670         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4671         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4672         table->next_idx++;
4673 }
4674
4675 static void
4676 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4677 {
4678         MonoDynamicTable *table;
4679         guint32 *values;
4680         char blob_size [6];
4681         guchar hash [20];
4682         char *b = blob_size;
4683         char *name, *sname;
4684         guint32 idx, offset;
4685
4686         if (rsrc->filename) {
4687                 name = mono_string_to_utf8 (rsrc->filename);
4688                 sname = g_path_get_basename (name);
4689         
4690                 table = &assembly->tables [MONO_TABLE_FILE];
4691                 table->rows++;
4692                 alloc_table (table, table->rows);
4693                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4694                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4695                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4696                 g_free (sname);
4697
4698                 mono_sha1_get_digest_from_file (name, hash);
4699                 mono_metadata_encode_value (20, b, &b);
4700                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4701                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4702                 g_free (name);
4703                 idx = table->next_idx++;
4704                 rsrc->offset = 0;
4705                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4706         } else {
4707                 char sizebuf [4];
4708                 char *data;
4709                 guint len;
4710                 if (rsrc->data) {
4711                         data = mono_array_addr (rsrc->data, char, 0);
4712                         len = mono_array_length (rsrc->data);
4713                 } else {
4714                         data = NULL;
4715                         len = 0;
4716                 }
4717                 offset = len;
4718                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4719                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4720                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4721                 mono_image_add_stream_data (&assembly->resources, data, len);
4722
4723                 if (!mb->is_main)
4724                         /* 
4725                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4726                          * the main module, but that needs to reference the FILE table
4727                          * which isn't emitted yet.
4728                          */
4729                         return;
4730                 else
4731                         idx = 0;
4732         }
4733
4734         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4735 }
4736
4737 static void
4738 set_version_from_string (MonoString *version, guint32 *values)
4739 {
4740         gchar *ver, *p, *str;
4741         guint32 i;
4742         
4743         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4744         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4745         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4746         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4747         if (!version)
4748                 return;
4749         ver = str = mono_string_to_utf8 (version);
4750         for (i = 0; i < 4; ++i) {
4751                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4752                 switch (*p) {
4753                 case '.':
4754                         p++;
4755                         break;
4756                 case '*':
4757                         /* handle Revision and Build */
4758                         p++;
4759                         break;
4760                 }
4761                 ver = p;
4762         }
4763         g_free (str);
4764 }
4765
4766 static guint32
4767 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4768         gsize len;
4769         guint32 token = 0;
4770         char blob_size [6];
4771         char *b = blob_size;
4772
4773         if (!pkey)
4774                 return token;
4775
4776         len = mono_array_length (pkey);
4777         mono_metadata_encode_value (len, b, &b);
4778         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4779         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4780
4781         assembly->public_key = (guint8 *)g_malloc (len);
4782         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4783         assembly->public_key_len = len;
4784
4785         /* Special case: check for ECMA key (16 bytes) */
4786         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4787                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4788                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4789         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4790                 /* minimum key size (in 2.0) is 384 bits */
4791                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4792         } else {
4793                 /* FIXME - verifier */
4794                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4795                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4796         }
4797         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4798
4799         return token;
4800 }
4801
4802 static void
4803 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4804 {
4805         MonoDynamicTable *table;
4806         MonoDynamicImage *assembly;
4807         MonoReflectionAssemblyBuilder *assemblyb;
4808         MonoDomain *domain;
4809         guint32 *values;
4810         int i;
4811         guint32 module_index;
4812
4813         assemblyb = moduleb->assemblyb;
4814         assembly = moduleb->dynamic_image;
4815         domain = mono_object_domain (assemblyb);
4816
4817         /* Emit ASSEMBLY table */
4818         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4819         alloc_table (table, 1);
4820         values = table->values + MONO_ASSEMBLY_SIZE;
4821         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4822         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4823         if (assemblyb->culture) {
4824                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4825         } else {
4826                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4827         }
4828         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4829         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4830         set_version_from_string (assemblyb->version, values);
4831
4832         /* Emit FILE + EXPORTED_TYPE table */
4833         module_index = 0;
4834         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4835                 int j;
4836                 MonoReflectionModuleBuilder *file_module = 
4837                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4838                 if (file_module != moduleb) {
4839                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4840                         module_index ++;
4841                         if (file_module->types) {
4842                                 for (j = 0; j < file_module->num_types; ++j) {
4843                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4844                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4845                                 }
4846                         }
4847                 }
4848         }
4849         if (assemblyb->loaded_modules) {
4850                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4851                         MonoReflectionModule *file_module = 
4852                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4853                         mono_image_fill_file_table (domain, file_module, assembly);
4854                         module_index ++;
4855                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4856                 }
4857         }
4858         if (assemblyb->type_forwarders)
4859                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4860
4861         /* Emit MANIFESTRESOURCE table */
4862         module_index = 0;
4863         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4864                 int j;
4865                 MonoReflectionModuleBuilder *file_module = 
4866                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4867                 /* The table for the main module is emitted later */
4868                 if (file_module != moduleb) {
4869                         module_index ++;
4870                         if (file_module->resources) {
4871                                 int len = mono_array_length (file_module->resources);
4872                                 for (j = 0; j < len; ++j) {
4873                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4874                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4875                                 }
4876                         }
4877                 }
4878         }               
4879 }
4880
4881 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4882
4883 /*
4884  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4885  * for the modulebuilder @moduleb.
4886  * At the end of the process, method and field tokens are fixed up and the 
4887  * on-disk compressed metadata representation is created.
4888  * Return TRUE on success, or FALSE on failure and sets @error
4889  */
4890 gboolean
4891 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4892 {
4893         MonoDynamicTable *table;
4894         MonoDynamicImage *assembly;
4895         MonoReflectionAssemblyBuilder *assemblyb;
4896         MonoDomain *domain;
4897         MonoPtrArray types;
4898         guint32 *values;
4899         int i, j;
4900
4901         mono_error_init (error);
4902
4903         assemblyb = moduleb->assemblyb;
4904         assembly = moduleb->dynamic_image;
4905         domain = mono_object_domain (assemblyb);
4906
4907         if (assembly->text_rva)
4908                 return TRUE;
4909
4910         assembly->text_rva = START_TEXT_RVA;
4911
4912         if (moduleb->is_main) {
4913                 mono_image_emit_manifest (moduleb);
4914         }
4915
4916         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4917         table->rows = 1; /* .<Module> */
4918         table->next_idx++;
4919         alloc_table (table, table->rows);
4920         /*
4921          * Set the first entry.
4922          */
4923         values = table->values + table->columns;
4924         values [MONO_TYPEDEF_FLAGS] = 0;
4925         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4926         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4927         values [MONO_TYPEDEF_EXTENDS] = 0;
4928         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4929         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4930
4931         /* 
4932          * handle global methods 
4933          * FIXME: test what to do when global methods are defined in multiple modules.
4934          */
4935         if (moduleb->global_methods) {
4936                 table = &assembly->tables [MONO_TABLE_METHOD];
4937                 table->rows += mono_array_length (moduleb->global_methods);
4938                 alloc_table (table, table->rows);
4939                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4940                         mono_image_get_method_info (
4941                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4942         }
4943         if (moduleb->global_fields) {
4944                 table = &assembly->tables [MONO_TABLE_FIELD];
4945                 table->rows += mono_array_length (moduleb->global_fields);
4946                 alloc_table (table, table->rows);
4947                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4948                         mono_image_get_field_info (
4949                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4950         }
4951
4952         table = &assembly->tables [MONO_TABLE_MODULE];
4953         alloc_table (table, 1);
4954         mono_image_fill_module_table (domain, moduleb, assembly);
4955
4956         /* Collect all types into a list sorted by their table_idx */
4957         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4958
4959         if (moduleb->types)
4960                 for (i = 0; i < moduleb->num_types; ++i) {
4961                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4962                         collect_types (&types, type);
4963                 }
4964
4965         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4966         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4967         table->rows += mono_ptr_array_size (types);
4968         alloc_table (table, table->rows);
4969
4970         /*
4971          * Emit type names + namespaces at one place inside the string heap,
4972          * so load_class_names () needs to touch fewer pages.
4973          */
4974         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4975                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4976                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4977         }
4978         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4979                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4980                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4981         }
4982
4983         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4984                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4985                 mono_image_get_type_info (domain, type, assembly);
4986         }
4987
4988         /* 
4989          * table->rows is already set above and in mono_image_fill_module_table.
4990          */
4991         /* add all the custom attributes at the end, once all the indexes are stable */
4992         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
4993                 goto leave_types;
4994
4995         /* CAS assembly permissions */
4996         if (assemblyb->permissions_minimum)
4997                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4998         if (assemblyb->permissions_optional)
4999                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5000         if (assemblyb->permissions_refused)
5001                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5002
5003         if (!module_add_cattrs (assembly, moduleb, error))
5004                 goto leave_types;
5005
5006         /* fixup tokens */
5007         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5008
5009         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5010          * the final tokens and don't need another fixup pass. */
5011
5012         if (moduleb->global_methods) {
5013                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5014                         MonoReflectionMethodBuilder *mb = mono_array_get (
5015                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5016                         if (!mono_image_add_methodimpl (assembly, mb, error))
5017                                 goto leave_types;
5018                 }
5019         }
5020
5021         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5022                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5023                 if (type->methods) {
5024                         for (j = 0; j < type->num_methods; ++j) {
5025                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5026                                         type->methods, MonoReflectionMethodBuilder*, j);
5027
5028                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5029                                         goto leave_types;
5030                         }
5031                 }
5032         }
5033
5034         fixup_cattrs (assembly);
5035
5036 leave_types:
5037         mono_ptr_array_destroy (types);
5038 leave:
5039
5040         return mono_error_ok (error);
5041 }
5042
5043 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5044
5045 gboolean
5046 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5047 {
5048         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5049 }
5050
5051 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5052
5053
5054 typedef struct {
5055         guint32 import_lookup_table;
5056         guint32 timestamp;
5057         guint32 forwarder;
5058         guint32 name_rva;
5059         guint32 import_address_table_rva;
5060 } MonoIDT;
5061
5062 typedef struct {
5063         guint32 name_rva;
5064         guint32 flags;
5065 } MonoILT;
5066
5067 #ifndef DISABLE_REFLECTION_EMIT
5068
5069 /*
5070  * mono_image_insert_string:
5071  * @module: module builder object
5072  * @str: a string
5073  *
5074  * Insert @str into the user string stream of @module.
5075  */
5076 guint32
5077 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5078 {
5079         MonoDynamicImage *assembly;
5080         guint32 idx;
5081         char buf [16];
5082         char *b = buf;
5083         
5084         if (!module->dynamic_image)
5085                 mono_image_module_basic_init (module);
5086
5087         assembly = module->dynamic_image;
5088         
5089         if (assembly->save) {
5090                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5091                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5092 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5093         {
5094                 char *swapped = g_malloc (2 * mono_string_length (str));
5095                 const char *p = (const char*)mono_string_chars (str);
5096
5097                 swap_with_size (swapped, p, 2, mono_string_length (str));
5098                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5099                 g_free (swapped);
5100         }
5101 #else
5102                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5103 #endif
5104                 mono_image_add_stream_data (&assembly->us, "", 1);
5105         } else {
5106                 idx = assembly->us.index ++;
5107         }
5108
5109         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5110
5111         return MONO_TOKEN_STRING | idx;
5112 }
5113
5114 guint32
5115 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5116 {
5117         MonoClass *klass;
5118         guint32 token = 0;
5119         MonoMethodSignature *sig;
5120
5121         mono_error_init (error);
5122
5123         klass = obj->vtable->klass;
5124         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5125                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5126                 MonoMethodSignature *old;
5127                 guint32 sig_token, parent;
5128                 int nargs, i;
5129
5130                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5131
5132                 nargs = mono_array_length (opt_param_types);
5133                 old = mono_method_signature (method);
5134                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5135
5136                 sig->hasthis = old->hasthis;
5137                 sig->explicit_this = old->explicit_this;
5138                 sig->call_convention = old->call_convention;
5139                 sig->generic_param_count = old->generic_param_count;
5140                 sig->param_count = old->param_count + nargs;
5141                 sig->sentinelpos = old->param_count;
5142                 sig->ret = old->ret;
5143
5144                 for (i = 0; i < old->param_count; i++)
5145                         sig->params [i] = old->params [i];
5146
5147                 for (i = 0; i < nargs; i++) {
5148                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5149                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5150                 }
5151
5152                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5153                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5154                 parent >>= MONO_TYPEDEFORREF_BITS;
5155
5156                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5157                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5158
5159                 sig_token = method_encode_signature (assembly, sig);
5160                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5161         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5162                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5163                 ReflectionMethodBuilder rmb;
5164                 guint32 parent, sig_token;
5165                 int nopt_args, nparams, ngparams, i;
5166
5167                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5168                 rmb.opt_types = opt_param_types;
5169                 nopt_args = mono_array_length (opt_param_types);
5170
5171                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5172                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5173                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5174
5175                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5176                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5177                 sig->call_convention = rmb.call_conv;
5178                 sig->generic_param_count = ngparams;
5179                 sig->param_count = nparams + nopt_args;
5180                 sig->sentinelpos = nparams;
5181                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5182
5183                 for (i = 0; i < nparams; i++) {
5184                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5185                         sig->params [i] = mono_reflection_type_get_handle (rt);
5186                 }
5187
5188                 for (i = 0; i < nopt_args; i++) {
5189                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5190                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5191                 }
5192
5193                 sig_token = method_builder_encode_signature (assembly, &rmb);
5194
5195                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5196                 if (!mono_error_ok (error))
5197                         goto fail;
5198                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5199
5200                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5201                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5202
5203                 char *name = mono_string_to_utf8 (rmb.name);
5204                 token = mono_image_get_varargs_method_token (
5205                         assembly, parent, name, sig_token);
5206                 g_free (name);
5207         } else {
5208                 g_error ("requested method token for %s\n", klass->name);
5209         }
5210
5211         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5212         register_dyn_token (assembly, token, obj);
5213         return token;
5214 fail:
5215         g_assert (!mono_error_ok (error));
5216         return 0;
5217 }
5218
5219 /*
5220  * mono_image_create_token:
5221  * @assembly: a dynamic assembly
5222  * @obj:
5223  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5224  *
5225  * Get a token to insert in the IL code stream for the given MemberInfo.
5226  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5227  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5228  * entry.
5229  */
5230 guint32
5231 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5232                          gboolean create_open_instance, gboolean register_token,
5233                          MonoError *error)
5234 {
5235         MonoClass *klass;
5236         guint32 token = 0;
5237
5238         mono_error_init (error);
5239
5240         klass = obj->vtable->klass;
5241
5242         /* Check for user defined reflection objects */
5243         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5244         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5245                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5246                 return 0;
5247         }
5248
5249         if (strcmp (klass->name, "MethodBuilder") == 0) {
5250                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5251                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5252
5253                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5254                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5255                 else
5256                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5257                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5258         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5259                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5260                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5261
5262                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5263                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5264                 else
5265                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5266                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5267         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5268                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5269                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5270                 if (tb->generic_params) {
5271                         token = mono_image_get_generic_field_token (assembly, fb);
5272                 } else {
5273                         if (tb->module->dynamic_image == assembly) {
5274                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5275                         } else {
5276                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5277                         }
5278                 }
5279         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5280                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5281                 if (create_open_instance && tb->generic_params) {
5282                         MonoType *type;
5283                         init_type_builder_generics (obj);
5284                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5285                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5286                         token = mono_metadata_token_from_dor (token);
5287                 } else if (tb->module->dynamic_image == assembly) {
5288                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5289                 } else {
5290                         MonoType *type;
5291                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5292                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5293                 }
5294         } else if (strcmp (klass->name, "MonoType") == 0) {
5295                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5296                 MonoClass *mc = mono_class_from_mono_type (type);
5297                 token = mono_metadata_token_from_dor (
5298                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5299         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5300                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5301                 token = mono_metadata_token_from_dor (
5302                         mono_image_typedef_or_ref (assembly, type));
5303         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5304                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5305                 token = mono_metadata_token_from_dor (
5306                         mono_image_typedef_or_ref (assembly, type));
5307         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5308                    strcmp (klass->name, "MonoMethod") == 0 ||
5309                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5310                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5311                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5312                 if (m->method->is_inflated) {
5313                         if (create_open_instance)
5314                                 token = mono_image_get_methodspec_token (assembly, m->method);
5315                         else
5316                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5317                 } else if ((m->method->klass->image == &assembly->image) &&
5318                          !m->method->klass->generic_class) {
5319                         static guint32 method_table_idx = 0xffffff;
5320                         if (m->method->klass->wastypebuilder) {
5321                                 /* we use the same token as the one that was assigned
5322                                  * to the Methodbuilder.
5323                                  * FIXME: do the equivalent for Fields.
5324                                  */
5325                                 token = m->method->token;
5326                         } else {
5327                                 /*
5328                                  * Each token should have a unique index, but the indexes are
5329                                  * assigned by managed code, so we don't know about them. An
5330                                  * easy solution is to count backwards...
5331                                  */
5332                                 method_table_idx --;
5333                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5334                         }
5335                 } else {
5336                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5337                 }
5338                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5339         } else if (strcmp (klass->name, "MonoField") == 0) {
5340                 MonoReflectionField *f = (MonoReflectionField *)obj;
5341                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5342                         static guint32 field_table_idx = 0xffffff;
5343                         field_table_idx --;
5344                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5345                 } else {
5346                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5347                 }
5348                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5349         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5350                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5351                 token = mono_image_get_array_token (assembly, m);
5352         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5353                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5354                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5355         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5356                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5357                 token = mono_metadata_token_from_dor (
5358                         mono_image_typedef_or_ref (assembly, type));
5359         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5360                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5361                 token = mono_image_get_field_on_inst_token (assembly, f);
5362         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5363                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5364                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5365         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5366                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5367                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5368         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5369                 MonoReflectionType *type = (MonoReflectionType *)obj;
5370                 token = mono_metadata_token_from_dor (
5371                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5372         } else {
5373                 g_error ("requested token for %s\n", klass->name);
5374         }
5375
5376         if (register_token)
5377                 mono_image_register_token (assembly, token, obj);
5378
5379         return token;
5380 }
5381
5382 /*
5383  * mono_image_register_token:
5384  *
5385  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5386  * the Module.ResolveXXXToken () methods to work.
5387  */
5388 void
5389 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5390 {
5391         MonoObject *prev;
5392
5393         dynamic_image_lock (assembly);
5394         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5395         if (prev) {
5396                 /* There could be multiple MethodInfo objects with the same token */
5397                 //g_assert (prev == obj);
5398         } else {
5399                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5400         }
5401         dynamic_image_unlock (assembly);
5402 }
5403
5404 static MonoDynamicImage*
5405 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5406 {
5407         static const guchar entrycode [16] = {0xff, 0x25, 0};
5408         MonoDynamicImage *image;
5409         int i;
5410
5411         const char *version;
5412
5413         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5414                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5415         else
5416                 version = mono_get_runtime_info ()->runtime_version;
5417
5418 #if HAVE_BOEHM_GC
5419         /* The MonoGHashTable's need GC tracking */
5420         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5421 #else
5422         image = g_new0 (MonoDynamicImage, 1);
5423 #endif
5424
5425         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5426         
5427         /*g_print ("created image %p\n", image);*/
5428         /* keep in sync with image.c */
5429         image->image.name = assembly_name;
5430         image->image.assembly_name = image->image.name; /* they may be different */
5431         image->image.module_name = module_name;
5432         image->image.version = g_strdup (version);
5433         image->image.md_version_major = 1;
5434         image->image.md_version_minor = 1;
5435         image->image.dynamic = TRUE;
5436
5437         image->image.references = g_new0 (MonoAssembly*, 1);
5438         image->image.references [0] = NULL;
5439
5440         mono_image_init (&image->image);
5441
5442         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5443         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5444         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5445         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5446         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5447         image->handleref = g_hash_table_new (NULL, NULL);
5448         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5449         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5450         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5451         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5452         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5453         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5454         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5455         image->gen_params = g_ptr_array_new ();
5456         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5457
5458         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5459         string_heap_init (&image->sheap);
5460         mono_image_add_stream_data (&image->us, "", 1);
5461         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5462         /* import tables... */
5463         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5464         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5465         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5466         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5467         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5468         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5469         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5470         stream_data_align (&image->code);
5471
5472         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5473
5474         for (i=0; i < MONO_TABLE_NUM; ++i) {
5475                 image->tables [i].next_idx = 1;
5476                 image->tables [i].columns = table_sizes [i];
5477         }
5478
5479         image->image.assembly = (MonoAssembly*)assembly;
5480         image->run = assembly->run;
5481         image->save = assembly->save;
5482         image->pe_kind = 0x1; /* ILOnly */
5483         image->machine = 0x14c; /* I386 */
5484         
5485         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5486
5487         dynamic_images_lock ();
5488
5489         if (!dynamic_images)
5490                 dynamic_images = g_ptr_array_new ();
5491
5492         g_ptr_array_add (dynamic_images, image);
5493
5494         dynamic_images_unlock ();
5495
5496         return image;
5497 }
5498 #endif
5499
5500 static void
5501 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5502 {
5503         g_free (key);
5504 }
5505
5506 static void
5507 release_hashtable (MonoGHashTable **hash)
5508 {
5509         if (*hash) {
5510                 mono_g_hash_table_destroy (*hash);
5511                 *hash = NULL;
5512         }
5513 }
5514
5515 void
5516 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5517 {
5518         release_hashtable (&image->token_fixups);
5519         release_hashtable (&image->handleref_managed);
5520         release_hashtable (&image->tokens);
5521         release_hashtable (&image->remapped_tokens);
5522         release_hashtable (&image->generic_def_objects);
5523         release_hashtable (&image->methodspec);
5524 }
5525
5526 // Free dynamic image pass one: Free resources but not image itself
5527 void
5528 mono_dynamic_image_free (MonoDynamicImage *image)
5529 {
5530         MonoDynamicImage *di = image;
5531         GList *list;
5532         int i;
5533
5534         if (di->methodspec)
5535                 mono_g_hash_table_destroy (di->methodspec);
5536         if (di->typespec)
5537                 g_hash_table_destroy (di->typespec);
5538         if (di->typeref)
5539                 g_hash_table_destroy (di->typeref);
5540         if (di->handleref)
5541                 g_hash_table_destroy (di->handleref);
5542         if (di->handleref_managed)
5543                 mono_g_hash_table_destroy (di->handleref_managed);
5544         if (di->tokens)
5545                 mono_g_hash_table_destroy (di->tokens);
5546         if (di->remapped_tokens)
5547                 mono_g_hash_table_destroy (di->remapped_tokens);
5548         if (di->generic_def_objects)
5549                 mono_g_hash_table_destroy (di->generic_def_objects);
5550         if (di->blob_cache) {
5551                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5552                 g_hash_table_destroy (di->blob_cache);
5553         }
5554         if (di->standalonesig_cache)
5555                 g_hash_table_destroy (di->standalonesig_cache);
5556         for (list = di->array_methods; list; list = list->next) {
5557                 ArrayMethod *am = (ArrayMethod *)list->data;
5558                 g_free (am->sig);
5559                 g_free (am->name);
5560                 g_free (am);
5561         }
5562         g_list_free (di->array_methods);
5563         if (di->gen_params) {
5564                 for (i = 0; i < di->gen_params->len; i++) {
5565                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5566                         mono_gc_deregister_root ((char*) &entry->gparam);
5567                         g_free (entry);
5568                 }
5569                 g_ptr_array_free (di->gen_params, TRUE);
5570         }
5571         if (di->token_fixups)
5572                 mono_g_hash_table_destroy (di->token_fixups);
5573         if (di->method_to_table_idx)
5574                 g_hash_table_destroy (di->method_to_table_idx);
5575         if (di->field_to_table_idx)
5576                 g_hash_table_destroy (di->field_to_table_idx);
5577         if (di->method_aux_hash)
5578                 g_hash_table_destroy (di->method_aux_hash);
5579         if (di->vararg_aux_hash)
5580                 g_hash_table_destroy (di->vararg_aux_hash);
5581         g_free (di->strong_name);
5582         g_free (di->win32_res);
5583         if (di->public_key)
5584                 g_free (di->public_key);
5585
5586         /*g_print ("string heap destroy for image %p\n", di);*/
5587         mono_dynamic_stream_reset (&di->sheap);
5588         mono_dynamic_stream_reset (&di->code);
5589         mono_dynamic_stream_reset (&di->resources);
5590         mono_dynamic_stream_reset (&di->us);
5591         mono_dynamic_stream_reset (&di->blob);
5592         mono_dynamic_stream_reset (&di->tstream);
5593         mono_dynamic_stream_reset (&di->guid);
5594         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5595                 g_free (di->tables [i].values);
5596         }
5597
5598         dynamic_images_lock ();
5599
5600         if (dynamic_images)
5601                 g_ptr_array_remove (dynamic_images, di);
5602
5603         dynamic_images_unlock ();
5604 }
5605
5606 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5607 void
5608 mono_dynamic_image_free_image (MonoDynamicImage *image)
5609 {
5610         /* See create_dynamic_mono_image () */
5611 #if HAVE_BOEHM_GC
5612         /* Allocated using GC_MALLOC */
5613 #else
5614         g_free (image);
5615 #endif
5616 }
5617
5618 #ifndef DISABLE_REFLECTION_EMIT
5619
5620 /*
5621  * mono_image_basic_init:
5622  * @assembly: an assembly builder object
5623  *
5624  * Create the MonoImage that represents the assembly builder and setup some
5625  * of the helper hash table and the basic metadata streams.
5626  */
5627 void
5628 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5629 {
5630         MonoDynamicAssembly *assembly;
5631         MonoDynamicImage *image;
5632         MonoDomain *domain = mono_object_domain (assemblyb);
5633         
5634         if (assemblyb->dynamic_assembly)
5635                 return;
5636
5637 #if HAVE_BOEHM_GC
5638         /* assembly->assembly.image might be GC allocated */
5639         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5640 #else
5641         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5642 #endif
5643
5644         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5645         
5646         assembly->assembly.ref_count = 1;
5647         assembly->assembly.dynamic = TRUE;
5648         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5649         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5650         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5651         if (assemblyb->culture)
5652                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5653         else
5654                 assembly->assembly.aname.culture = g_strdup ("");
5655
5656         if (assemblyb->version) {
5657                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5658                         char **version = g_strsplit (vstr, ".", 4);
5659                         char **parts = version;
5660                         assembly->assembly.aname.major = atoi (*parts++);
5661                         assembly->assembly.aname.minor = atoi (*parts++);
5662                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5663                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5664
5665                         g_strfreev (version);
5666                         g_free (vstr);
5667         } else {
5668                         assembly->assembly.aname.major = 0;
5669                         assembly->assembly.aname.minor = 0;
5670                         assembly->assembly.aname.build = 0;
5671                         assembly->assembly.aname.revision = 0;
5672         }
5673
5674         assembly->run = assemblyb->access != 2;
5675         assembly->save = assemblyb->access != 1;
5676         assembly->domain = domain;
5677
5678         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5679         image->initial_image = TRUE;
5680         assembly->assembly.aname.name = image->image.name;
5681         assembly->assembly.image = &image->image;
5682         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5683                 /* -1 to correct for the trailing NULL byte */
5684                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5685                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5686                 }
5687                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5688         }
5689
5690         mono_domain_assemblies_lock (domain);
5691         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5692         mono_domain_assemblies_unlock (domain);
5693
5694         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5695         
5696         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5697         
5698         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5699 }
5700
5701 #endif /* !DISABLE_REFLECTION_EMIT */
5702
5703 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5704
5705 static int
5706 calc_section_size (MonoDynamicImage *assembly)
5707 {
5708         int nsections = 0;
5709
5710         /* alignment constraints */
5711         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5712         g_assert ((assembly->code.index % 4) == 0);
5713         assembly->meta_size += 3;
5714         assembly->meta_size &= ~3;
5715         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5716         g_assert ((assembly->resources.index % 4) == 0);
5717
5718         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5719         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5720         nsections++;
5721
5722         if (assembly->win32_res) {
5723                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5724
5725                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5726                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5727                 nsections++;
5728         }
5729
5730         assembly->sections [MONO_SECTION_RELOC].size = 12;
5731         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5732         nsections++;
5733
5734         return nsections;
5735 }
5736
5737 typedef struct {
5738         guint32 id;
5739         guint32 offset;
5740         GSList *children;
5741         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5742 } ResTreeNode;
5743
5744 static int
5745 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5746 {
5747         ResTreeNode *t1 = (ResTreeNode*)a;
5748         ResTreeNode *t2 = (ResTreeNode*)b;
5749
5750         return t1->id - t2->id;
5751 }
5752
5753 /*
5754  * resource_tree_create:
5755  *
5756  *  Organize the resources into a resource tree.
5757  */
5758 static ResTreeNode *
5759 resource_tree_create (MonoArray *win32_resources)
5760 {
5761         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5762         GSList *l;
5763         int i;
5764
5765         tree = g_new0 (ResTreeNode, 1);
5766         
5767         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5768                 MonoReflectionWin32Resource *win32_res =
5769                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5770
5771                 /* Create node */
5772
5773                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5774                 lang_node = g_new0 (ResTreeNode, 1);
5775                 lang_node->id = win32_res->lang_id;
5776                 lang_node->win32_res = win32_res;
5777
5778                 /* Create type node if neccesary */
5779                 type_node = NULL;
5780                 for (l = tree->children; l; l = l->next)
5781                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5782                                 type_node = (ResTreeNode*)l->data;
5783                                 break;
5784                         }
5785
5786                 if (!type_node) {
5787                         type_node = g_new0 (ResTreeNode, 1);
5788                         type_node->id = win32_res->res_type;
5789
5790                         /* 
5791                          * The resource types have to be sorted otherwise
5792                          * Windows Explorer can't display the version information.
5793                          */
5794                         tree->children = g_slist_insert_sorted (tree->children, 
5795                                 type_node, resource_tree_compare_by_id);
5796                 }
5797
5798                 /* Create res node if neccesary */
5799                 res_node = NULL;
5800                 for (l = type_node->children; l; l = l->next)
5801                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5802                                 res_node = (ResTreeNode*)l->data;
5803                                 break;
5804                         }
5805
5806                 if (!res_node) {
5807                         res_node = g_new0 (ResTreeNode, 1);
5808                         res_node->id = win32_res->res_id;
5809                         type_node->children = g_slist_append (type_node->children, res_node);
5810                 }
5811
5812                 res_node->children = g_slist_append (res_node->children, lang_node);
5813         }
5814
5815         return tree;
5816 }
5817
5818 /*
5819  * resource_tree_encode:
5820  * 
5821  *   Encode the resource tree into the format used in the PE file.
5822  */
5823 static void
5824 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5825 {
5826         char *entries;
5827         MonoPEResourceDir dir;
5828         MonoPEResourceDirEntry dir_entry;
5829         MonoPEResourceDataEntry data_entry;
5830         GSList *l;
5831         guint32 res_id_entries;
5832
5833         /*
5834          * For the format of the resource directory, see the article
5835          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5836          * Matt Pietrek
5837          */
5838
5839         memset (&dir, 0, sizeof (dir));
5840         memset (&dir_entry, 0, sizeof (dir_entry));
5841         memset (&data_entry, 0, sizeof (data_entry));
5842
5843         g_assert (sizeof (dir) == 16);
5844         g_assert (sizeof (dir_entry) == 8);
5845         g_assert (sizeof (data_entry) == 16);
5846
5847         node->offset = p - begin;
5848
5849         /* IMAGE_RESOURCE_DIRECTORY */
5850         res_id_entries = g_slist_length (node->children);
5851         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5852
5853         memcpy (p, &dir, sizeof (dir));
5854         p += sizeof (dir);
5855
5856         /* Reserve space for entries */
5857         entries = p;
5858         p += sizeof (dir_entry) * res_id_entries;
5859
5860         /* Write children */
5861         for (l = node->children; l; l = l->next) {
5862                 ResTreeNode *child = (ResTreeNode*)l->data;
5863
5864                 if (child->win32_res) {
5865                         guint32 size;
5866
5867                         child->offset = p - begin;
5868
5869                         /* IMAGE_RESOURCE_DATA_ENTRY */
5870                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5871                         size = mono_array_length (child->win32_res->res_data);
5872                         data_entry.rde_size = GUINT32_TO_LE (size);
5873
5874                         memcpy (p, &data_entry, sizeof (data_entry));
5875                         p += sizeof (data_entry);
5876
5877                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5878                         p += size;
5879                 } else {
5880                         resource_tree_encode (child, begin, p, &p);
5881                 }
5882         }
5883
5884         /* IMAGE_RESOURCE_ENTRY */
5885         for (l = node->children; l; l = l->next) {
5886                 ResTreeNode *child = (ResTreeNode*)l->data;
5887
5888                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5889                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5890
5891                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5892                 entries += sizeof (dir_entry);
5893         }
5894
5895         *endbuf = p;
5896 }
5897
5898 static void
5899 resource_tree_free (ResTreeNode * node)
5900 {
5901         GSList * list;
5902         for (list = node->children; list; list = list->next)
5903                 resource_tree_free ((ResTreeNode*)list->data);
5904         g_slist_free(node->children);
5905         g_free (node);
5906 }
5907
5908 static void
5909 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5910 {
5911         char *buf;
5912         char *p;
5913         guint32 size, i;
5914         MonoReflectionWin32Resource *win32_res;
5915         ResTreeNode *tree;
5916
5917         if (!assemblyb->win32_resources)
5918                 return;
5919
5920         /*
5921          * Resources are stored in a three level tree inside the PE file.
5922          * - level one contains a node for each type of resource
5923          * - level two contains a node for each resource
5924          * - level three contains a node for each instance of a resource for a
5925          *   specific language.
5926          */
5927
5928         tree = resource_tree_create (assemblyb->win32_resources);
5929
5930         /* Estimate the size of the encoded tree */
5931         size = 0;
5932         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5933                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5934                 size += mono_array_length (win32_res->res_data);
5935         }
5936         /* Directory structure */
5937         size += mono_array_length (assemblyb->win32_resources) * 256;
5938         p = buf = (char *)g_malloc (size);
5939
5940         resource_tree_encode (tree, p, p, &p);
5941
5942         g_assert (p - buf <= size);
5943
5944         assembly->win32_res = (char *)g_malloc (p - buf);
5945         assembly->win32_res_size = p - buf;
5946         memcpy (assembly->win32_res, buf, p - buf);
5947
5948         g_free (buf);
5949         resource_tree_free (tree);
5950 }
5951
5952 static void
5953 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5954 {
5955         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5956         int i;
5957
5958         p += sizeof (MonoPEResourceDir);
5959         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5960                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5961                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5962                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5963                         fixup_resource_directory (res_section, child, rva);
5964                 } else {
5965                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5966                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5967                 }
5968
5969                 p += sizeof (MonoPEResourceDirEntry);
5970         }
5971 }
5972
5973 static void
5974 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5975 {
5976         guint32 dummy;
5977         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5978                 g_error ("WriteFile returned %d\n", GetLastError ());
5979 }
5980
5981 /*
5982  * mono_image_create_pefile:
5983  * @mb: a module builder object
5984  * 
5985  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5986  * assembly->pefile where it can be easily retrieved later in chunks.
5987  */
5988 void
5989 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5990 {
5991         MonoError error;
5992         MonoMSDOSHeader *msdos;
5993         MonoDotNetHeader *header;
5994         MonoSectionTable *section;
5995         MonoCLIHeader *cli_header;
5996         guint32 size, image_size, virtual_base, text_offset;
5997         guint32 header_start, section_start, file_offset, virtual_offset;
5998         MonoDynamicImage *assembly;
5999         MonoReflectionAssemblyBuilder *assemblyb;
6000         MonoDynamicStream pefile_stream = {0};
6001         MonoDynamicStream *pefile = &pefile_stream;
6002         int i, nsections;
6003         guint32 *rva, value;
6004         guchar *p;
6005         static const unsigned char msheader[] = {
6006                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6007                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6008                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6009                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6010                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6011                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6012                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6013                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6014         };
6015
6016         assemblyb = mb->assemblyb;
6017
6018         mono_image_basic_init (assemblyb);
6019         assembly = mb->dynamic_image;
6020
6021         assembly->pe_kind = assemblyb->pe_kind;
6022         assembly->machine = assemblyb->machine;
6023         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6024         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6025         
6026         if (!mono_image_build_metadata (mb, &error))
6027                 mono_error_raise_exception (&error); /* FIXME don't raise here */
6028         
6029
6030         if (mb->is_main && assemblyb->resources) {
6031                 int len = mono_array_length (assemblyb->resources);
6032                 for (i = 0; i < len; ++i)
6033                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6034         }
6035
6036         if (mb->resources) {
6037                 int len = mono_array_length (mb->resources);
6038                 for (i = 0; i < len; ++i)
6039                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6040         }
6041
6042         build_compressed_metadata (assembly);
6043
6044         if (mb->is_main)
6045                 assembly_add_win32_resources (assembly, assemblyb);
6046
6047         nsections = calc_section_size (assembly);
6048         
6049         /* The DOS header and stub */
6050         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6051         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6052
6053         /* the dotnet header */
6054         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6055
6056         /* the section tables */
6057         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6058
6059         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6060         virtual_offset = VIRT_ALIGN;
6061         image_size = 0;
6062
6063         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6064                 if (!assembly->sections [i].size)
6065                         continue;
6066                 /* align offsets */
6067                 file_offset += FILE_ALIGN - 1;
6068                 file_offset &= ~(FILE_ALIGN - 1);
6069                 virtual_offset += VIRT_ALIGN - 1;
6070                 virtual_offset &= ~(VIRT_ALIGN - 1);
6071
6072                 assembly->sections [i].offset = file_offset;
6073                 assembly->sections [i].rva = virtual_offset;
6074
6075                 file_offset += assembly->sections [i].size;
6076                 virtual_offset += assembly->sections [i].size;
6077                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6078         }
6079
6080         file_offset += FILE_ALIGN - 1;
6081         file_offset &= ~(FILE_ALIGN - 1);
6082
6083         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6084
6085         /* back-patch info */
6086         msdos = (MonoMSDOSHeader*)pefile->data;
6087         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6088
6089         header = (MonoDotNetHeader*)(pefile->data + header_start);
6090         header->pesig [0] = 'P';
6091         header->pesig [1] = 'E';
6092         
6093         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6094         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6095         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6096         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6097         if (assemblyb->pekind == 1) {
6098                 /* it's a dll */
6099                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6100         } else {
6101                 /* it's an exe */
6102                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6103         }
6104
6105         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6106
6107         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6108         header->pe.pe_major = 6;
6109         header->pe.pe_minor = 0;
6110         size = assembly->sections [MONO_SECTION_TEXT].size;
6111         size += FILE_ALIGN - 1;
6112         size &= ~(FILE_ALIGN - 1);
6113         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6114         size = assembly->sections [MONO_SECTION_RSRC].size;
6115         size += FILE_ALIGN - 1;
6116         size &= ~(FILE_ALIGN - 1);
6117         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6118         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6119         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6120         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6121         /* pe_rva_entry_point always at the beginning of the text section */
6122         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6123
6124         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6125         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6126         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6127         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6128         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6129         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6130         size = section_start;
6131         size += FILE_ALIGN - 1;
6132         size &= ~(FILE_ALIGN - 1);
6133         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6134         size = image_size;
6135         size += VIRT_ALIGN - 1;
6136         size &= ~(VIRT_ALIGN - 1);
6137         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6138
6139         /*
6140         // Translate the PEFileKind value to the value expected by the Windows loader
6141         */
6142         {
6143                 short kind;
6144
6145                 /*
6146                 // PEFileKinds.Dll == 1
6147                 // PEFileKinds.ConsoleApplication == 2
6148                 // PEFileKinds.WindowApplication == 3
6149                 //
6150                 // need to get:
6151                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6152                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6153                 */
6154                 if (assemblyb->pekind == 3)
6155                         kind = 2;
6156                 else
6157                         kind = 3;
6158                 
6159                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6160         }    
6161         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6162         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6163         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6164         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6165         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6166         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6167
6168         /* fill data directory entries */
6169
6170         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6171         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6172
6173         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6174         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6175
6176         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6177         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6178         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6179         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6180         /* patch entrypoint name */
6181         if (assemblyb->pekind == 1)
6182                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6183         else
6184                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6185         /* patch imported function RVA name */
6186         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6187         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6188
6189         /* the import table */
6190         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6191         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6192         /* patch imported dll RVA name and other entries in the dir */
6193         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6194         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6195         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6196         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6197         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6198         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6199
6200         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6201         value = (assembly->text_rva + assembly->imp_names_offset);
6202         *p++ = (value) & 0xff;
6203         *p++ = (value >> 8) & (0xff);
6204         *p++ = (value >> 16) & (0xff);
6205         *p++ = (value >> 24) & (0xff);
6206
6207         /* the CLI header info */
6208         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6209         cli_header->ch_size = GUINT32_FROM_LE (72);
6210         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6211         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6212         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6213         if (assemblyb->entry_point) {
6214                 guint32 table_idx = 0;
6215                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6216                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6217                         table_idx = methodb->table_idx;
6218                 } else {
6219                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6220                 }
6221                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6222         } else {
6223                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6224         }
6225         /* The embedded managed resources */
6226         text_offset = assembly->text_rva + assembly->code.index;
6227         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6228         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6229         text_offset += assembly->resources.index;
6230         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6231         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6232         text_offset += assembly->meta_size;
6233         if (assembly->strong_name_size) {
6234                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6235                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6236                 text_offset += assembly->strong_name_size;
6237         }
6238
6239         /* write the section tables and section content */
6240         section = (MonoSectionTable*)(pefile->data + section_start);
6241         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6242                 static const char section_names [][7] = {
6243                         ".text", ".rsrc", ".reloc"
6244                 };
6245                 if (!assembly->sections [i].size)
6246                         continue;
6247                 strcpy (section->st_name, section_names [i]);
6248                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6249                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6250                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6251                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6252                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6253                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6254                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6255                 section ++;
6256         }
6257         
6258         checked_write_file (file, pefile->data, pefile->index);
6259         
6260         mono_dynamic_stream_reset (pefile);
6261         
6262         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6263                 if (!assembly->sections [i].size)
6264                         continue;
6265                 
6266                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6267                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6268                 
6269                 switch (i) {
6270                 case MONO_SECTION_TEXT:
6271                         /* patch entry point */
6272                         p = (guchar*)(assembly->code.data + 2);
6273                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6274                         *p++ = (value) & 0xff;
6275                         *p++ = (value >> 8) & 0xff;
6276                         *p++ = (value >> 16) & 0xff;
6277                         *p++ = (value >> 24) & 0xff;
6278                 
6279                         checked_write_file (file, assembly->code.data, assembly->code.index);
6280                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6281                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6282                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6283                                 
6284
6285                         g_free (assembly->image.raw_metadata);
6286                         break;
6287                 case MONO_SECTION_RELOC: {
6288                         struct {
6289                                 guint32 page_rva;
6290                                 guint32 block_size;
6291                                 guint16 type_and_offset;
6292                                 guint16 term;
6293                         } reloc;
6294                         
6295                         g_assert (sizeof (reloc) == 12);
6296                         
6297                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6298                         reloc.block_size = GUINT32_FROM_LE (12);
6299                         
6300                         /* 
6301                          * the entrypoint is always at the start of the text section 
6302                          * 3 is IMAGE_REL_BASED_HIGHLOW
6303                          * 2 is patch_size_rva - text_rva
6304                          */
6305                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6306                         reloc.term = 0;
6307                         
6308                         checked_write_file (file, &reloc, sizeof (reloc));
6309                         
6310                         break;
6311                 }
6312                 case MONO_SECTION_RSRC:
6313                         if (assembly->win32_res) {
6314
6315                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6316                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6317                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6318                         }
6319                         break;
6320                 default:
6321                         g_assert_not_reached ();
6322                 }
6323         }
6324         
6325         /* check that the file is properly padded */
6326         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6327                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6328         if (! SetEndOfFile (file))
6329                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6330         
6331         mono_dynamic_stream_reset (&assembly->code);
6332         mono_dynamic_stream_reset (&assembly->us);
6333         mono_dynamic_stream_reset (&assembly->blob);
6334         mono_dynamic_stream_reset (&assembly->guid);
6335         mono_dynamic_stream_reset (&assembly->sheap);
6336
6337         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6338         g_hash_table_destroy (assembly->blob_cache);
6339         assembly->blob_cache = NULL;
6340 }
6341
6342 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6343
6344 void
6345 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6346 {
6347         g_assert_not_reached ();
6348 }
6349
6350 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6351
6352 #ifndef DISABLE_REFLECTION_EMIT
6353
6354 MonoReflectionModule *
6355 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6356 {
6357         char *name;
6358         MonoImage *image;
6359         MonoImageOpenStatus status;
6360         MonoDynamicAssembly *assembly;
6361         guint32 module_count;
6362         MonoImage **new_modules;
6363         gboolean *new_modules_loaded;
6364         
6365         name = mono_string_to_utf8 (fileName);
6366
6367         image = mono_image_open (name, &status);
6368         if (!image) {
6369                 MonoException *exc;
6370                 if (status == MONO_IMAGE_ERROR_ERRNO)
6371                         exc = mono_get_exception_file_not_found (fileName);
6372                 else
6373                         exc = mono_get_exception_bad_image_format (name);
6374                 g_free (name);
6375                 mono_raise_exception (exc);
6376         }
6377
6378         g_free (name);
6379
6380         assembly = ab->dynamic_assembly;
6381         image->assembly = (MonoAssembly*)assembly;
6382
6383         module_count = image->assembly->image->module_count;
6384         new_modules = g_new0 (MonoImage *, module_count + 1);
6385         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6386
6387         if (image->assembly->image->modules)
6388                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6389         if (image->assembly->image->modules_loaded)
6390                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6391         new_modules [module_count] = image;
6392         new_modules_loaded [module_count] = TRUE;
6393         mono_image_addref (image);
6394
6395         g_free (image->assembly->image->modules);
6396         image->assembly->image->modules = new_modules;
6397         image->assembly->image->modules_loaded = new_modules_loaded;
6398         image->assembly->image->module_count ++;
6399
6400         mono_assembly_load_references (image, &status);
6401         if (status) {
6402                 mono_image_close (image);
6403                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6404         }
6405
6406         return mono_module_get_object (mono_domain_get (), image);
6407 }
6408
6409 #endif /* DISABLE_REFLECTION_EMIT */
6410
6411 /*
6412  * We need to return always the same object for MethodInfo, FieldInfo etc..
6413  * but we need to consider the reflected type.
6414  * type uses a different hash, since it uses custom hash/equal functions.
6415  */
6416
6417 typedef struct {
6418         gpointer item;
6419         MonoClass *refclass;
6420 } ReflectedEntry;
6421
6422 static gboolean
6423 reflected_equal (gconstpointer a, gconstpointer b) {
6424         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6425         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6426
6427         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6428 }
6429
6430 static guint
6431 reflected_hash (gconstpointer a) {
6432         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6433         return mono_aligned_addr_hash (ea->item);
6434 }
6435
6436 #define CHECK_OBJECT(t,p,k)     \
6437         do {    \
6438                 t _obj; \
6439                 ReflectedEntry e;       \
6440                 e.item = (p);   \
6441                 e.refclass = (k);       \
6442                 mono_domain_lock (domain);      \
6443                 if (!domain->refobject_hash)    \
6444                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6445                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6446                         mono_domain_unlock (domain);    \
6447                         return _obj;    \
6448                 }       \
6449         mono_domain_unlock (domain); \
6450         } while (0)
6451
6452 #ifdef HAVE_BOEHM_GC
6453 /* ReflectedEntry doesn't need to be GC tracked */
6454 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6455 #define FREE_REFENTRY(entry) g_free ((entry))
6456 #define REFENTRY_REQUIRES_CLEANUP
6457 #else
6458 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6459 /* FIXME: */
6460 #define FREE_REFENTRY(entry)
6461 #endif
6462
6463 #define CACHE_OBJECT(t,p,o,k)   \
6464         do {    \
6465                 t _obj; \
6466         ReflectedEntry pe; \
6467         pe.item = (p); \
6468         pe.refclass = (k); \
6469         mono_domain_lock (domain); \
6470                 if (!domain->refobject_hash)    \
6471                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6472         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6473         if (!_obj) { \
6474                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6475                     e->item = (p);      \
6476                     e->refclass = (k);  \
6477                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6478             _obj = o; \
6479         } \
6480                 mono_domain_unlock (domain);    \
6481         return _obj; \
6482         } while (0)
6483
6484 static void
6485 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6486 {
6487         mono_domain_lock (domain);
6488         if (domain->refobject_hash) {
6489         ReflectedEntry pe;
6490                 gpointer orig_pe, orig_value;
6491
6492                 pe.item = o;
6493                 pe.refclass = klass;
6494                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6495                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6496                         FREE_REFENTRY (orig_pe);
6497                 }
6498         }
6499         mono_domain_unlock (domain);
6500 }
6501
6502 #ifdef REFENTRY_REQUIRES_CLEANUP
6503 static void
6504 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6505 {
6506         FREE_REFENTRY (key);
6507 }
6508 #endif
6509
6510 void
6511 mono_reflection_cleanup_domain (MonoDomain *domain)
6512 {
6513         if (domain->refobject_hash) {
6514 /*let's avoid scanning the whole hashtable if not needed*/
6515 #ifdef REFENTRY_REQUIRES_CLEANUP
6516                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6517 #endif
6518                 mono_g_hash_table_destroy (domain->refobject_hash);
6519                 domain->refobject_hash = NULL;
6520         }
6521 }
6522
6523 #ifndef DISABLE_REFLECTION_EMIT
6524 static gpointer
6525 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6526 {
6527         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6528 }
6529
6530 static gpointer
6531 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6532 {
6533         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6534 }
6535
6536 void
6537 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6538 {
6539         MonoDynamicImage *image = moduleb->dynamic_image;
6540         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6541         if (!image) {
6542                 MonoError error;
6543                 int module_count;
6544                 MonoImage **new_modules;
6545                 MonoImage *ass;
6546                 char *name, *fqname;
6547                 /*
6548                  * FIXME: we already created an image in mono_image_basic_init (), but
6549                  * we don't know which module it belongs to, since that is only 
6550                  * determined at assembly save time.
6551                  */
6552                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6553                 name = mono_string_to_utf8 (ab->name);
6554                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6555                 if (!mono_error_ok (&error)) {
6556                         g_free (name);
6557                         mono_error_raise_exception (&error);
6558                 }
6559                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6560
6561                 moduleb->module.image = &image->image;
6562                 moduleb->dynamic_image = image;
6563                 register_module (mono_object_domain (moduleb), moduleb, image);
6564
6565                 /* register the module with the assembly */
6566                 ass = ab->dynamic_assembly->assembly.image;
6567                 module_count = ass->module_count;
6568                 new_modules = g_new0 (MonoImage *, module_count + 1);
6569
6570                 if (ass->modules)
6571                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6572                 new_modules [module_count] = &image->image;
6573                 mono_image_addref (&image->image);
6574
6575                 g_free (ass->modules);
6576                 ass->modules = new_modules;
6577                 ass->module_count ++;
6578         }
6579 }
6580
6581 void
6582 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6583 {
6584         MonoDynamicImage *image = moduleb->dynamic_image;
6585
6586         g_assert (type->type);
6587         image->wrappers_type = mono_class_from_mono_type (type->type);
6588 }
6589
6590 #endif
6591
6592 /*
6593  * mono_assembly_get_object:
6594  * @domain: an app domain
6595  * @assembly: an assembly
6596  *
6597  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6598  */
6599 MonoReflectionAssembly*
6600 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6601 {
6602         MonoError error;
6603         static MonoClass *assembly_type;
6604         MonoReflectionAssembly *res;
6605         
6606         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6607         if (!assembly_type) {
6608                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6609                 if (klass == NULL)
6610                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6611                 g_assert (klass);
6612                 assembly_type = klass;
6613         }
6614         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6615         mono_error_raise_exception (&error); /* FIXME don't raise here */
6616         res->assembly = assembly;
6617
6618         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6619 }
6620
6621
6622
6623 MonoReflectionModule*   
6624 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6625 {
6626         MonoError error;
6627         static MonoClass *module_type;
6628         MonoReflectionModule *res;
6629         char* basename;
6630         
6631         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6632         if (!module_type) {
6633                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6634                 if (klass == NULL)
6635                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6636                 g_assert (klass);
6637                 module_type = klass;
6638         }
6639         res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6640         mono_error_raise_exception (&error); /* FIXME don't raise here */
6641
6642         res->image = image;
6643         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6644
6645         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6646         basename = g_path_get_basename (image->name);
6647         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6648         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6649         
6650         g_free (basename);
6651
6652         if (image->assembly->image == image) {
6653                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6654         } else {
6655                 int i;
6656                 res->token = 0;
6657                 if (image->assembly->image->modules) {
6658                         for (i = 0; i < image->assembly->image->module_count; i++) {
6659                                 if (image->assembly->image->modules [i] == image)
6660                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6661                         }
6662                         g_assert (res->token);
6663                 }
6664         }
6665
6666         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6667 }
6668
6669 MonoReflectionModule*   
6670 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6671 {
6672         MonoError error;
6673         static MonoClass *module_type;
6674         MonoReflectionModule *res;
6675         MonoTableInfo *table;
6676         guint32 cols [MONO_FILE_SIZE];
6677         const char *name;
6678         guint32 i, name_idx;
6679         const char *val;
6680         
6681         if (!module_type) {
6682                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6683                 if (klass == NULL)
6684                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6685                 g_assert (klass);
6686                 module_type = klass;
6687         }
6688         res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6689         mono_error_raise_exception (&error); /* FIXME don't raise here */
6690
6691         table = &image->tables [MONO_TABLE_FILE];
6692         g_assert (table_index < table->rows);
6693         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6694
6695         res->image = NULL;
6696         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6697         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6698
6699         /* Check whenever the row has a corresponding row in the moduleref table */
6700         table = &image->tables [MONO_TABLE_MODULEREF];
6701         for (i = 0; i < table->rows; ++i) {
6702                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6703                 val = mono_metadata_string_heap (image, name_idx);
6704                 if (strcmp (val, name) == 0)
6705                         res->image = image->modules [i];
6706         }
6707
6708         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6709         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6710         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6711         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6712         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6713
6714         return res;
6715 }
6716
6717 static gboolean
6718 verify_safe_for_managed_space (MonoType *type)
6719 {
6720         switch (type->type) {
6721 #ifdef DEBUG_HARDER
6722         case MONO_TYPE_ARRAY:
6723                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6724         case MONO_TYPE_PTR:
6725                 return verify_safe_for_managed_space (type->data.type);
6726         case MONO_TYPE_SZARRAY:
6727                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6728         case MONO_TYPE_GENERICINST: {
6729                 MonoGenericInst *inst = type->data.generic_class->inst;
6730                 int i;
6731                 if (!inst->is_open)
6732                         break;
6733                 for (i = 0; i < inst->type_argc; ++i)
6734                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6735                                 return FALSE;
6736                 return TRUE;
6737         }
6738 #endif
6739         case MONO_TYPE_VAR:
6740         case MONO_TYPE_MVAR:
6741                 return TRUE;
6742         default:
6743                 return TRUE;
6744         }
6745 }
6746
6747 static MonoType*
6748 mono_type_normalize (MonoType *type)
6749 {
6750         int i;
6751         MonoGenericClass *gclass;
6752         MonoGenericInst *ginst;
6753         MonoClass *gtd;
6754         MonoGenericContainer *gcontainer;
6755         MonoType **argv = NULL;
6756         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6757
6758         if (type->type != MONO_TYPE_GENERICINST)
6759                 return type;
6760
6761         gclass = type->data.generic_class;
6762         ginst = gclass->context.class_inst;
6763         if (!ginst->is_open)
6764                 return type;
6765
6766         gtd = gclass->container_class;
6767         gcontainer = gtd->generic_container;
6768         argv = g_newa (MonoType*, ginst->type_argc);
6769
6770         for (i = 0; i < ginst->type_argc; ++i) {
6771                 MonoType *t = ginst->type_argv [i], *norm;
6772                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6773                         is_denorm_gtd = FALSE;
6774                 norm = mono_type_normalize (t);
6775                 argv [i] = norm;
6776                 if (norm != t)
6777                         requires_rebind = TRUE;
6778         }
6779
6780         if (is_denorm_gtd)
6781                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6782
6783         if (requires_rebind) {
6784                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6785                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6786         }
6787
6788         return type;
6789 }
6790 /*
6791  * mono_type_get_object:
6792  * @domain: an app domain
6793  * @type: a type
6794  *
6795  * Return an System.MonoType object representing the type @type.
6796  */
6797 MonoReflectionType*
6798 mono_type_get_object (MonoDomain *domain, MonoType *type)
6799 {
6800         MonoError error;
6801         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6802         mono_error_raise_exception (&error);
6803
6804         return ret;
6805 }
6806
6807 MonoReflectionType*
6808 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6809 {
6810         MonoType *norm_type;
6811         MonoReflectionType *res;
6812         MonoClass *klass;
6813
6814         mono_error_init (error);
6815
6816         klass = mono_class_from_mono_type (type);
6817
6818         /*we must avoid using @type as it might have come
6819          * from a mono_metadata_type_dup and the caller
6820          * expects that is can be freed.
6821          * Using the right type from 
6822          */
6823         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6824
6825         /* void is very common */
6826         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6827                 return (MonoReflectionType*)domain->typeof_void;
6828
6829         /*
6830          * If the vtable of the given class was already created, we can use
6831          * the MonoType from there and avoid all locking and hash table lookups.
6832          * 
6833          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6834          * that the resulting object is different.   
6835          */
6836         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6837                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6838                 if (vtable && vtable->type)
6839                         return (MonoReflectionType *)vtable->type;
6840         }
6841
6842         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6843         mono_domain_lock (domain);
6844         if (!domain->type_hash)
6845                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6846                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6847         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6848                 mono_domain_unlock (domain);
6849                 mono_loader_unlock ();
6850                 return res;
6851         }
6852
6853         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6854          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6855          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6856          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6857          * artifact of how generics are encoded and should be transparent to managed code so we
6858          * need to weed out this diference when retrieving managed System.Type objects.
6859          */
6860         norm_type = mono_type_normalize (type);
6861         if (norm_type != type) {
6862                 res = mono_type_get_object_checked (domain, norm_type, error);
6863                 if (!mono_error_ok (error))
6864                         return NULL;
6865                 mono_g_hash_table_insert (domain->type_hash, type, res);
6866                 mono_domain_unlock (domain);
6867                 mono_loader_unlock ();
6868                 return res;
6869         }
6870
6871         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6872         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6873                 g_assert (0);
6874
6875         if (!verify_safe_for_managed_space (type)) {
6876                 mono_domain_unlock (domain);
6877                 mono_loader_unlock ();
6878                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6879                 return NULL;
6880         }
6881
6882         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6883                 gboolean is_type_done = TRUE;
6884                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6885                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6886                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6887                 */
6888                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6889                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6890
6891                         if (gparam->owner && gparam->owner->is_method) {
6892                                 MonoMethod *method = gparam->owner->owner.method;
6893                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6894                                         is_type_done = FALSE;
6895                         } else if (gparam->owner && !gparam->owner->is_method) {
6896                                 MonoClass *klass = gparam->owner->owner.klass;
6897                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6898                                         is_type_done = FALSE;
6899                         }
6900                 } 
6901
6902                 /* g_assert_not_reached (); */
6903                 /* should this be considered an error condition? */
6904                 if (is_type_done && !type->byref) {
6905                         mono_domain_unlock (domain);
6906                         mono_loader_unlock ();
6907                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
6908                 }
6909         }
6910         /* This is stored in vtables/JITted code so it has to be pinned */
6911         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6912         if (!mono_error_ok (error))
6913                 return NULL;
6914
6915         res->type = type;
6916         mono_g_hash_table_insert (domain->type_hash, type, res);
6917
6918         if (type->type == MONO_TYPE_VOID)
6919                 domain->typeof_void = (MonoObject*)res;
6920
6921         mono_domain_unlock (domain);
6922         mono_loader_unlock ();
6923         return res;
6924 }
6925
6926 /*
6927  * mono_method_get_object:
6928  * @domain: an app domain
6929  * @method: a method
6930  * @refclass: the reflected type (can be NULL)
6931  *
6932  * Return an System.Reflection.MonoMethod object representing the method @method.
6933  */
6934 MonoReflectionMethod*
6935 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6936 {
6937         MonoError error;
6938         MonoReflectionMethod *ret = NULL;
6939         ret = mono_method_get_object_checked (domain, method, refclass, &error);
6940         mono_error_raise_exception (&error);
6941         return ret;
6942 }
6943
6944 /*
6945  * mono_method_get_object_checked:
6946  * @domain: an app domain
6947  * @method: a method
6948  * @refclass: the reflected type (can be NULL)
6949  * @error: set on error.
6950  *
6951  * Return an System.Reflection.MonoMethod object representing the method @method.
6952  * Returns NULL and sets @error on error.
6953  */
6954 MonoReflectionMethod*
6955 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
6956 {
6957         /*
6958          * We use the same C representation for methods and constructors, but the type 
6959          * name in C# is different.
6960          */
6961         static MonoClass *System_Reflection_MonoMethod = NULL;
6962         static MonoClass *System_Reflection_MonoCMethod = NULL;
6963         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6964         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6965         MonoReflectionType *rt;
6966         MonoClass *klass;
6967         MonoReflectionMethod *ret;
6968
6969         mono_error_init (error);
6970
6971         if (method->is_inflated) {
6972                 MonoReflectionGenericMethod *gret;
6973
6974                 if (!refclass)
6975                         refclass = method->klass;
6976                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6977                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6978                         if (!System_Reflection_MonoGenericCMethod) {
6979                                 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
6980                                 if (!mono_error_ok (error))
6981                                         goto leave;
6982                         }
6983                         klass = System_Reflection_MonoGenericCMethod;
6984                 } else {
6985                         if (!System_Reflection_MonoGenericMethod) {
6986                                 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
6987                                 if (!mono_error_ok (error))
6988                                         goto leave;
6989                         }
6990                         klass = System_Reflection_MonoGenericMethod;
6991                 }
6992                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
6993                 if (!mono_error_ok (error))
6994                         goto leave;
6995                 gret->method.method = method;
6996
6997                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6998
6999                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7000                 if (!mono_error_ok (error))
7001                     goto leave;
7002
7003                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7004
7005                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7006         }
7007
7008         if (!refclass)
7009                 refclass = method->klass;
7010
7011         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7012         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7013                 if (!System_Reflection_MonoCMethod) {
7014                         System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
7015                         if (!mono_error_ok (error))
7016                                 goto leave;
7017                 }
7018                 klass = System_Reflection_MonoCMethod;
7019         }
7020         else {
7021                 if (!System_Reflection_MonoMethod) {
7022                         System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
7023                         if (!mono_error_ok (error))
7024                                 goto leave;
7025                 }
7026                 klass = System_Reflection_MonoMethod;
7027         }
7028         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7029         if (!mono_error_ok (error))
7030                 goto leave;
7031         ret->method = method;
7032
7033         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7034         if (!mono_error_ok (error))
7035                 goto leave;
7036
7037         MONO_OBJECT_SETREF (ret, reftype, rt);
7038
7039         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7040
7041 leave:
7042         g_assert (!mono_error_ok (error));
7043         return NULL;
7044 }
7045
7046 /*
7047  * mono_method_clear_object:
7048  *
7049  *   Clear the cached reflection objects for the dynamic method METHOD.
7050  */
7051 void
7052 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7053 {
7054         MonoClass *klass;
7055         g_assert (method_is_dynamic (method));
7056
7057         klass = method->klass;
7058         while (klass) {
7059                 clear_cached_object (domain, method, klass);
7060                 klass = klass->parent;
7061         }
7062         /* Added by mono_param_get_objects () */
7063         clear_cached_object (domain, &(method->signature), NULL);
7064         klass = method->klass;
7065         while (klass) {
7066                 clear_cached_object (domain, &(method->signature), klass);
7067                 klass = klass->parent;
7068         }
7069 }
7070
7071 /*
7072  * mono_field_get_object:
7073  * @domain: an app domain
7074  * @klass: a type
7075  * @field: a field
7076  *
7077  * Return an System.Reflection.MonoField object representing the field @field
7078  * in class @klass.
7079  */
7080 MonoReflectionField*
7081 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7082 {
7083         MonoError error;
7084         MonoReflectionField *result;
7085         result = mono_field_get_object_checked (domain, klass, field, &error);
7086         mono_error_raise_exception (&error);
7087         return result;
7088 }
7089
7090 /*
7091  * mono_field_get_object_checked:
7092  * @domain: an app domain
7093  * @klass: a type
7094  * @field: a field
7095  * @error: set on error
7096  *
7097  * Return an System.Reflection.MonoField object representing the field @field
7098  * in class @klass. On error, returns NULL and sets @error.
7099  */
7100 MonoReflectionField*
7101 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7102 {
7103         MonoReflectionType *rt;
7104         MonoReflectionField *res;
7105         static MonoClass *monofield_klass;
7106
7107         mono_error_init (error);
7108
7109         CHECK_OBJECT (MonoReflectionField *, field, klass);
7110         if (!monofield_klass)
7111                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7112         res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7113         mono_error_raise_exception (error); /* FIXME don't raise here */
7114         res->klass = klass;
7115         res->field = field;
7116         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7117
7118         if (is_field_on_inst (field)) {
7119                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7120
7121                 rt = mono_type_get_object_checked (domain, field->type, error);
7122                 if (!mono_error_ok (error))
7123                         return NULL;
7124
7125                 MONO_OBJECT_SETREF (res, type, rt);
7126         } else {
7127                 if (field->type) {
7128                         rt = mono_type_get_object_checked (domain, field->type, error);
7129                         if (!mono_error_ok (error))
7130                                 return NULL;
7131
7132                         MONO_OBJECT_SETREF (res, type, rt);
7133                 }
7134                 res->attrs = mono_field_get_flags (field);
7135         }
7136         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7137 }
7138
7139 /*
7140  * mono_property_get_object:
7141  * @domain: an app domain
7142  * @klass: a type
7143  * @property: a property
7144  *
7145  * Return an System.Reflection.MonoProperty object representing the property @property
7146  * in class @klass.
7147  */
7148 MonoReflectionProperty*
7149 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7150 {
7151         MonoError error;
7152         MonoReflectionProperty *res;
7153         static MonoClass *monoproperty_klass;
7154
7155         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7156         if (!monoproperty_klass)
7157                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7158         res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7159         mono_error_raise_exception (&error); /* FIXME don't raise here */
7160         res->klass = klass;
7161         res->property = property;
7162         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7163 }
7164
7165 /*
7166  * mono_event_get_object:
7167  * @domain: an app domain
7168  * @klass: a type
7169  * @event: a event
7170  *
7171  * Return an System.Reflection.MonoEvent object representing the event @event
7172  * in class @klass.
7173  */
7174 MonoReflectionEvent*
7175 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7176 {
7177         MonoError error;
7178         MonoReflectionEvent *res;
7179         MonoReflectionMonoEvent *mono_event;
7180         static MonoClass *monoevent_klass;
7181
7182         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7183         if (!monoevent_klass)
7184                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7185         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7186         mono_error_raise_exception (&error); /* FIXME don't raise here */
7187         mono_event->klass = klass;
7188         mono_event->event = event;
7189         res = (MonoReflectionEvent*)mono_event;
7190         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7191 }
7192
7193 /**
7194  * mono_get_reflection_missing_object:
7195  * @domain: Domain where the object lives
7196  *
7197  * Returns the System.Reflection.Missing.Value singleton object
7198  * (of type System.Reflection.Missing).
7199  *
7200  * Used as the value for ParameterInfo.DefaultValue when Optional
7201  * is present
7202  */
7203 static MonoObject *
7204 mono_get_reflection_missing_object (MonoDomain *domain)
7205 {
7206         MonoObject *obj;
7207         static MonoClassField *missing_value_field = NULL;
7208         
7209         if (!missing_value_field) {
7210                 MonoClass *missing_klass;
7211                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7212                 mono_class_init (missing_klass);
7213                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7214                 g_assert (missing_value_field);
7215         }
7216         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7217         g_assert (obj);
7218         return obj;
7219 }
7220
7221 static MonoObject*
7222 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7223 {
7224         if (!*dbnull)
7225                 *dbnull = mono_get_dbnull_object (domain);
7226         return *dbnull;
7227 }
7228
7229 static MonoObject*
7230 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7231 {
7232         if (!*reflection_missing)
7233                 *reflection_missing = mono_get_reflection_missing_object (domain);
7234         return *reflection_missing;
7235 }
7236
7237 /*
7238  * mono_param_get_objects:
7239  * @domain: an app domain
7240  * @method: a method
7241  *
7242  * Return an System.Reflection.ParameterInfo array object representing the parameters
7243  * in the method @method.
7244  */
7245 MonoArray*
7246 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7247 {
7248         static MonoClass *System_Reflection_ParameterInfo;
7249         static MonoClass *System_Reflection_ParameterInfo_array;
7250         MonoError error;
7251         MonoArray *res = NULL;
7252         MonoReflectionMethod *member = NULL;
7253         MonoReflectionParameter *param = NULL;
7254         char **names, **blobs = NULL;
7255         guint32 *types = NULL;
7256         MonoType *type = NULL;
7257         MonoObject *dbnull = NULL;
7258         MonoObject *missing = NULL;
7259         MonoMarshalSpec **mspecs;
7260         MonoMethodSignature *sig;
7261         MonoVTable *pinfo_vtable;
7262         MonoReflectionType *rt;
7263         int i;
7264
7265         if (!System_Reflection_ParameterInfo_array) {
7266                 MonoClass *klass;
7267
7268                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7269                 if (!klass)
7270                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7271
7272                 mono_memory_barrier ();
7273                 System_Reflection_ParameterInfo = klass; 
7274
7275         
7276                 klass = mono_array_class_get (klass, 1);
7277                 mono_memory_barrier ();
7278                 System_Reflection_ParameterInfo_array = klass;
7279         }
7280
7281         sig = mono_method_signature_checked (method, &error);
7282         if (!mono_error_ok (&error))
7283                 mono_error_raise_exception (&error);
7284
7285         if (!sig->param_count) {
7286                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7287                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7288
7289                 return res;
7290         }
7291
7292         /* Note: the cache is based on the address of the signature into the method
7293          * since we already cache MethodInfos with the method as keys.
7294          */
7295         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7296
7297         member = mono_method_get_object_checked (domain, method, refclass, &error);
7298         mono_error_raise_exception (&error); /* FIXME don't raise here */
7299         names = g_new (char *, sig->param_count);
7300         mono_method_get_param_names (method, (const char **) names);
7301
7302         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7303         mono_method_get_marshal_info (method, mspecs);
7304
7305         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7306         mono_error_raise_exception (&error); /* FIXME don't raise here */
7307
7308         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7309         for (i = 0; i < sig->param_count; ++i) {
7310                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7311                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7312
7313                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7314                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7315
7316                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7317
7318                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7319
7320                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7321
7322                 param->PositionImpl = i;
7323                 param->AttrsImpl = sig->params [i]->attrs;
7324
7325                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7326                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7327                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7328                         else
7329                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7330                 } else {
7331
7332                         if (!blobs) {
7333                                 blobs = g_new0 (char *, sig->param_count);
7334                                 types = g_new0 (guint32, sig->param_count);
7335                                 get_default_param_value_blobs (method, blobs, types); 
7336                         }
7337
7338                         /* Build MonoType for the type from the Constant Table */
7339                         if (!type)
7340                                 type = g_new0 (MonoType, 1);
7341                         type->type = (MonoTypeEnum)types [i];
7342                         type->data.klass = NULL;
7343                         if (types [i] == MONO_TYPE_CLASS)
7344                                 type->data.klass = mono_defaults.object_class;
7345                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7346                                 /* For enums, types [i] contains the base type */
7347
7348                                         type->type = MONO_TYPE_VALUETYPE;
7349                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7350                         } else
7351                                 type->data.klass = mono_class_from_mono_type (type);
7352
7353                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7354
7355                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7356                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7357                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7358                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7359                                 else
7360                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7361                         }
7362                         
7363                 }
7364
7365                 if (mspecs [i + 1])
7366                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7367                 
7368                 mono_array_setref (res, i, param);
7369         }
7370         g_free (names);
7371         g_free (blobs);
7372         g_free (types);
7373         g_free (type);
7374
7375         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7376                 if (mspecs [i])
7377                         mono_metadata_free_marshal_spec (mspecs [i]);
7378         g_free (mspecs);
7379         
7380         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7381 }
7382
7383 MonoArray*
7384 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7385 {
7386         return mono_param_get_objects_internal (domain, method, NULL);
7387 }
7388
7389 /*
7390  * mono_method_body_get_object:
7391  * @domain: an app domain
7392  * @method: a method
7393  *
7394  * Return an System.Reflection.MethodBody object representing the method @method.
7395  */
7396 MonoReflectionMethodBody*
7397 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7398 {
7399         static MonoClass *System_Reflection_MethodBody = NULL;
7400         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7401         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7402         MonoError error;
7403         MonoReflectionMethodBody *ret;
7404         MonoMethodHeader *header;
7405         MonoImage *image;
7406         MonoReflectionType *rt;
7407         guint32 method_rva, local_var_sig_token;
7408     char *ptr;
7409         unsigned char format, flags;
7410         int i;
7411
7412         /* for compatibility with .net */
7413     if (method_is_dynamic (method))
7414         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7415
7416         if (!System_Reflection_MethodBody)
7417                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7418         if (!System_Reflection_LocalVariableInfo)
7419                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7420         if (!System_Reflection_ExceptionHandlingClause)
7421                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7422
7423         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7424
7425         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7426                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7427             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7428                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7429             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7430                 return NULL;
7431
7432         image = method->klass->image;
7433         header = mono_method_get_header (method);
7434
7435         if (!image_is_dynamic (image)) {
7436                 /* Obtain local vars signature token */
7437                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7438                 ptr = mono_image_rva_map (image, method_rva);
7439                 flags = *(const unsigned char *) ptr;
7440                 format = flags & METHOD_HEADER_FORMAT_MASK;
7441                 switch (format){
7442                 case METHOD_HEADER_TINY_FORMAT:
7443                         local_var_sig_token = 0;
7444                         break;
7445                 case METHOD_HEADER_FAT_FORMAT:
7446                         ptr += 2;
7447                         ptr += 2;
7448                         ptr += 4;
7449                         local_var_sig_token = read32 (ptr);
7450                         break;
7451                 default:
7452                         g_assert_not_reached ();
7453                 }
7454         } else
7455                 local_var_sig_token = 0; //FIXME
7456
7457         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7458         mono_error_raise_exception (&error); /* FIXME don't raise here */
7459
7460         ret->init_locals = header->init_locals;
7461         ret->max_stack = header->max_stack;
7462         ret->local_var_sig_token = local_var_sig_token;
7463         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7464         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7465
7466         /* Locals */
7467         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7468         for (i = 0; i < header->num_locals; ++i) {
7469                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7470                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7471
7472                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7473                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7474
7475                 MONO_OBJECT_SETREF (info, local_type, rt);
7476
7477                 info->is_pinned = header->locals [i]->pinned;
7478                 info->local_index = i;
7479                 mono_array_setref (ret->locals, i, info);
7480         }
7481
7482         /* Exceptions */
7483         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7484         for (i = 0; i < header->num_clauses; ++i) {
7485                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7486                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7487                 MonoExceptionClause *clause = &header->clauses [i];
7488
7489                 info->flags = clause->flags;
7490                 info->try_offset = clause->try_offset;
7491                 info->try_length = clause->try_len;
7492                 info->handler_offset = clause->handler_offset;
7493                 info->handler_length = clause->handler_len;
7494                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7495                         info->filter_offset = clause->data.filter_offset;
7496                 else if (clause->data.catch_class) {
7497                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7498                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7499
7500                         MONO_OBJECT_SETREF (info, catch_type, rt);
7501                 }
7502
7503                 mono_array_setref (ret->clauses, i, info);
7504         }
7505
7506         mono_metadata_free_mh (header);
7507         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7508         return ret;
7509 }
7510
7511 /**
7512  * mono_get_dbnull_object:
7513  * @domain: Domain where the object lives
7514  *
7515  * Returns the System.DBNull.Value singleton object
7516  *
7517  * Used as the value for ParameterInfo.DefaultValue 
7518  */
7519 MonoObject *
7520 mono_get_dbnull_object (MonoDomain *domain)
7521 {
7522         MonoObject *obj;
7523         static MonoClassField *dbnull_value_field = NULL;
7524         
7525         if (!dbnull_value_field) {
7526                 MonoClass *dbnull_klass;
7527                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7528                 mono_class_init (dbnull_klass);
7529                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7530                 g_assert (dbnull_value_field);
7531         }
7532         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7533         g_assert (obj);
7534         return obj;
7535 }
7536
7537 static void
7538 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7539 {
7540         guint32 param_index, i, lastp, crow = 0;
7541         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7542         gint32 idx;
7543
7544         MonoClass *klass = method->klass;
7545         MonoImage *image = klass->image;
7546         MonoMethodSignature *methodsig = mono_method_signature (method);
7547
7548         MonoTableInfo *constt;
7549         MonoTableInfo *methodt;
7550         MonoTableInfo *paramt;
7551
7552         if (!methodsig->param_count)
7553                 return;
7554
7555         mono_class_init (klass);
7556
7557         if (image_is_dynamic (klass->image)) {
7558                 MonoReflectionMethodAux *aux;
7559                 if (method->is_inflated)
7560                         method = ((MonoMethodInflated*)method)->declaring;
7561                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7562                 if (aux && aux->param_defaults) {
7563                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7564                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7565                 }
7566                 return;
7567         }
7568
7569         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7570         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7571         constt = &image->tables [MONO_TABLE_CONSTANT];
7572
7573         idx = mono_method_get_index (method) - 1;
7574         g_assert (idx != -1);
7575
7576         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7577         if (idx + 1 < methodt->rows)
7578                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7579         else
7580                 lastp = paramt->rows + 1;
7581
7582         for (i = param_index; i < lastp; ++i) {
7583                 guint32 paramseq;
7584
7585                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7586                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7587
7588                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7589                         continue;
7590
7591                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7592                 if (!crow) {
7593                         continue;
7594                 }
7595         
7596                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7597                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7598                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7599         }
7600
7601         return;
7602 }
7603
7604 MonoObject *
7605 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7606 {
7607         MonoError error;
7608         void *retval;
7609         MonoClass *klass;
7610         MonoObject *object;
7611         MonoType *basetype = type;
7612
7613         if (!blob)
7614                 return NULL;
7615         
7616         klass = mono_class_from_mono_type (type);
7617         if (klass->valuetype) {
7618                 object = mono_object_new_checked (domain, klass, &error);
7619                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7620                 retval = ((gchar *) object + sizeof (MonoObject));
7621                 if (klass->enumtype)
7622                         basetype = mono_class_enum_basetype (klass);
7623         } else {
7624                 retval = &object;
7625         }
7626                         
7627         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7628                 return object;
7629         else
7630                 return NULL;
7631 }
7632
7633 static int
7634 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7635         int found_sep;
7636         char *s;
7637         gboolean quoted = FALSE;
7638
7639         memset (assembly, 0, sizeof (MonoAssemblyName));
7640         assembly->culture = "";
7641         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7642
7643         if (*p == '"') {
7644                 quoted = TRUE;
7645                 p++;
7646         }
7647         assembly->name = p;
7648         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7649                 p++;
7650         if (quoted) {
7651                 if (*p != '"')
7652                         return 1;
7653                 *p = 0;
7654                 p++;
7655         }
7656         if (*p != ',')
7657                 return 1;
7658         *p = 0;
7659         /* Remove trailing whitespace */
7660         s = p - 1;
7661         while (*s && g_ascii_isspace (*s))
7662                 *s-- = 0;
7663         p ++;
7664         while (g_ascii_isspace (*p))
7665                 p++;
7666         while (*p) {
7667                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7668                         p += 8;
7669                         assembly->major = strtoul (p, &s, 10);
7670                         if (s == p || *s != '.')
7671                                 return 1;
7672                         p = ++s;
7673                         assembly->minor = strtoul (p, &s, 10);
7674                         if (s == p || *s != '.')
7675                                 return 1;
7676                         p = ++s;
7677                         assembly->build = strtoul (p, &s, 10);
7678                         if (s == p || *s != '.')
7679                                 return 1;
7680                         p = ++s;
7681                         assembly->revision = strtoul (p, &s, 10);
7682                         if (s == p)
7683                                 return 1;
7684                         p = s;
7685                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7686                         p += 8;
7687                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7688                                 assembly->culture = "";
7689                                 p += 7;
7690                         } else {
7691                                 assembly->culture = p;
7692                                 while (*p && *p != ',') {
7693                                         p++;
7694                                 }
7695                         }
7696                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7697                         p += 15;
7698                         if (strncmp (p, "null", 4) == 0) {
7699                                 p += 4;
7700                         } else {
7701                                 int len;
7702                                 gchar *start = p;
7703                                 while (*p && *p != ',') {
7704                                         p++;
7705                                 }
7706                                 len = (p - start + 1);
7707                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7708                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7709                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7710                         }
7711                 } else {
7712                         while (*p && *p != ',')
7713                                 p++;
7714                 }
7715                 found_sep = 0;
7716                 while (g_ascii_isspace (*p) || *p == ',') {
7717                         *p++ = 0;
7718                         found_sep = 1;
7719                         continue;
7720                 }
7721                 /* failed */
7722                 if (!found_sep)
7723                         return 1;
7724         }
7725
7726         return 0;
7727 }
7728
7729 /*
7730  * mono_reflection_parse_type:
7731  * @name: type name
7732  *
7733  * Parse a type name as accepted by the GetType () method and output the info
7734  * extracted in the info structure.
7735  * the name param will be mangled, so, make a copy before passing it to this function.
7736  * The fields in info will be valid until the memory pointed to by name is valid.
7737  *
7738  * See also mono_type_get_name () below.
7739  *
7740  * Returns: 0 on parse error.
7741  */
7742 static int
7743 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7744                              MonoTypeNameParse *info)
7745 {
7746         char *start, *p, *w, *last_point, *startn;
7747         int in_modifiers = 0;
7748         int isbyref = 0, rank = 0, isptr = 0;
7749
7750         start = p = w = name;
7751
7752         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7753         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7754         info->name = info->name_space = NULL;
7755         info->nested = NULL;
7756         info->modifiers = NULL;
7757         info->type_arguments = NULL;
7758
7759         /* last_point separates the namespace from the name */
7760         last_point = NULL;
7761         /* Skips spaces */
7762         while (*p == ' ') p++, start++, w++, name++;
7763
7764         while (*p) {
7765                 switch (*p) {
7766                 case '+':
7767                         *p = 0; /* NULL terminate the name */
7768                         startn = p + 1;
7769                         info->nested = g_list_append (info->nested, startn);
7770                         /* we have parsed the nesting namespace + name */
7771                         if (info->name)
7772                                 break;
7773                         if (last_point) {
7774                                 info->name_space = start;
7775                                 *last_point = 0;
7776                                 info->name = last_point + 1;
7777                         } else {
7778                                 info->name_space = (char *)"";
7779                                 info->name = start;
7780                         }
7781                         break;
7782                 case '.':
7783                         last_point = p;
7784                         break;
7785                 case '\\':
7786                         ++p;
7787                         break;
7788                 case '&':
7789                 case '*':
7790                 case '[':
7791                 case ',':
7792                 case ']':
7793                         in_modifiers = 1;
7794                         break;
7795                 default:
7796                         break;
7797                 }
7798                 if (in_modifiers)
7799                         break;
7800                 // *w++ = *p++;
7801                 p++;
7802         }
7803         
7804         if (!info->name) {
7805                 if (last_point) {
7806                         info->name_space = start;
7807                         *last_point = 0;
7808                         info->name = last_point + 1;
7809                 } else {
7810                         info->name_space = (char *)"";
7811                         info->name = start;
7812                 }
7813         }
7814         while (*p) {
7815                 switch (*p) {
7816                 case '&':
7817                         if (isbyref) /* only one level allowed by the spec */
7818                                 return 0;
7819                         isbyref = 1;
7820                         isptr = 0;
7821                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7822                         *p++ = 0;
7823                         break;
7824                 case '*':
7825                         if (isbyref) /* pointer to ref not okay */
7826                                 return 0;
7827                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7828                         isptr = 1;
7829                         *p++ = 0;
7830                         break;
7831                 case '[':
7832                         if (isbyref) /* array of ref and generic ref are not okay */
7833                                 return 0;
7834                         //Decide if it's an array of a generic argument list
7835                         *p++ = 0;
7836
7837                         if (!*p) //XXX test
7838                                 return 0;
7839                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7840                                 isptr = 0;
7841                                 rank = 1;
7842                                 while (*p) {
7843                                         if (*p == ']')
7844                                                 break;
7845                                         if (*p == ',')
7846                                                 rank++;
7847                                         else if (*p == '*') /* '*' means unknown lower bound */
7848                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7849                                         else
7850                                                 return 0;
7851                                         ++p;
7852                                 }
7853                                 if (*p++ != ']')
7854                                         return 0;
7855                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7856                         } else {
7857                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7858                                         return 0;
7859                                 isptr = 0;
7860                                 info->type_arguments = g_ptr_array_new ();
7861                                 while (*p) {
7862                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7863                                         gboolean fqname = FALSE;
7864
7865                                         g_ptr_array_add (info->type_arguments, subinfo);
7866
7867                                         while (*p == ' ') p++;
7868                                         if (*p == '[') {
7869                                                 p++;
7870                                                 fqname = TRUE;
7871                                         }
7872
7873                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7874                                                 return 0;
7875
7876                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7877                                         if (fqname && (*p != ']')) {
7878                                                 char *aname;
7879
7880                                                 if (*p != ',')
7881                                                         return 0;
7882                                                 *p++ = 0;
7883
7884                                                 aname = p;
7885                                                 while (*p && (*p != ']'))
7886                                                         p++;
7887
7888                                                 if (*p != ']')
7889                                                         return 0;
7890
7891                                                 *p++ = 0;
7892                                                 while (*aname) {
7893                                                         if (g_ascii_isspace (*aname)) {
7894                                                                 ++aname;
7895                                                                 continue;
7896                                                         }
7897                                                         break;
7898                                                 }
7899                                                 if (!*aname ||
7900                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7901                                                         return 0;
7902                                         } else if (fqname && (*p == ']')) {
7903                                                 *p++ = 0;
7904                                         }
7905                                         if (*p == ']') {
7906                                                 *p++ = 0;
7907                                                 break;
7908                                         } else if (!*p) {
7909                                                 return 0;
7910                                         }
7911                                         *p++ = 0;
7912                                 }
7913                         }
7914                         break;
7915                 case ']':
7916                         if (is_recursed)
7917                                 goto end;
7918                         return 0;
7919                 case ',':
7920                         if (is_recursed)
7921                                 goto end;
7922                         *p++ = 0;
7923                         while (*p) {
7924                                 if (g_ascii_isspace (*p)) {
7925                                         ++p;
7926                                         continue;
7927                                 }
7928                                 break;
7929                         }
7930                         if (!*p)
7931                                 return 0; /* missing assembly name */
7932                         if (!assembly_name_to_aname (&info->assembly, p))
7933                                 return 0;
7934                         break;
7935                 default:
7936                         return 0;
7937                 }
7938                 if (info->assembly.name)
7939                         break;
7940         }
7941         // *w = 0; /* terminate class name */
7942  end:
7943         if (!info->name || !*info->name)
7944                 return 0;
7945         if (endptr)
7946                 *endptr = p;
7947         /* add other consistency checks */
7948         return 1;
7949 }
7950
7951
7952 /**
7953  * mono_identifier_unescape_type_name_chars:
7954  * @identifier: the display name of a mono type
7955  *
7956  * Returns:
7957  *  The name in internal form, that is without escaping backslashes.
7958  *
7959  *  The string is modified in place!
7960  */
7961 char*
7962 mono_identifier_unescape_type_name_chars(char* identifier)
7963 {
7964         char *w, *r;
7965         if (!identifier)
7966                 return NULL;
7967         for (w = r = identifier; *r != 0; r++)
7968         {
7969                 char c = *r;
7970                 if (c == '\\') {
7971                         r++;
7972                         if (*r == 0)
7973                                 break;
7974                         c = *r;
7975                 }
7976                 *w = c;
7977                 w++;
7978         }
7979         if (w != r)
7980                 *w = 0;
7981         return identifier;
7982 }
7983
7984 void
7985 mono_identifier_unescape_info (MonoTypeNameParse* info);
7986
7987 static void
7988 unescape_each_type_argument(void* data, void* user_data)
7989 {
7990         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7991         mono_identifier_unescape_info (info);
7992 }
7993
7994 static void
7995 unescape_each_nested_name (void* data, void* user_data)
7996 {
7997         char* nested_name = (char*) data;
7998         mono_identifier_unescape_type_name_chars(nested_name);
7999 }
8000
8001 /**
8002  * mono_identifier_unescape_info:
8003  *
8004  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8005  *
8006  * Returns: nothing.
8007  *
8008  * Destructively updates the info by unescaping the identifiers that
8009  * comprise the type namespace, name, nested types (if any) and
8010  * generic type arguments (if any).
8011  *
8012  * The resulting info has the names in internal form.
8013  *
8014  */
8015 void
8016 mono_identifier_unescape_info (MonoTypeNameParse *info)
8017 {
8018         if (!info)
8019                 return;
8020         mono_identifier_unescape_type_name_chars(info->name_space);
8021         mono_identifier_unescape_type_name_chars(info->name);
8022         // but don't escape info->assembly
8023         if (info->type_arguments)
8024                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8025         if (info->nested)
8026                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8027 }
8028
8029 int
8030 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8031 {
8032         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8033         if (ok) {
8034                 mono_identifier_unescape_info (info);
8035         }
8036         return ok;
8037 }
8038
8039 static MonoType*
8040 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8041 {
8042         gboolean type_resolve = FALSE;
8043         MonoType *type;
8044         MonoImage *rootimage = image;
8045
8046         if (info->assembly.name) {
8047                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8048                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8049                         /* 
8050                          * This could happen in the AOT compiler case when the search hook is not
8051                          * installed.
8052                          */
8053                         assembly = image->assembly;
8054                 if (!assembly) {
8055                         /* then we must load the assembly ourselve - see #60439 */
8056                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8057                         if (!assembly)
8058                                 return NULL;
8059                 }
8060                 image = assembly->image;
8061         } else if (!image) {
8062                 image = mono_defaults.corlib;
8063         }
8064
8065         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8066         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8067                 image = mono_defaults.corlib;
8068                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8069         }
8070
8071         return type;
8072 }
8073
8074 static MonoType*
8075 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
8076 {
8077         MonoError error;
8078         MonoClass *klass;
8079         GList *mod;
8080         int modval;
8081         gboolean bounded = FALSE;
8082         
8083         if (!image)
8084                 image = mono_defaults.corlib;
8085
8086         if (!rootimage)
8087                 rootimage = mono_defaults.corlib;
8088
8089         if (ignorecase) {
8090                 MonoError error;
8091                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
8092                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
8093         } else {
8094                 klass = mono_class_from_name (image, info->name_space, info->name);
8095         }
8096         if (!klass)
8097                 return NULL;
8098         for (mod = info->nested; mod; mod = mod->next) {
8099                 gpointer iter = NULL;
8100                 MonoClass *parent;
8101
8102                 parent = klass;
8103                 mono_class_init (parent);
8104
8105                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8106                         char *lastp;
8107                         char *nested_name, *nested_nspace;
8108                         gboolean match = TRUE;
8109
8110                         lastp = strrchr ((const char *)mod->data, '.');
8111                         if (lastp) {
8112                                 /* Nested classes can have namespaces */
8113                                 int nspace_len;
8114
8115                                 nested_name = g_strdup (lastp + 1);
8116                                 nspace_len = lastp - (char*)mod->data;
8117                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8118                                 memcpy (nested_nspace, mod->data, nspace_len);
8119                                 nested_nspace [nspace_len] = '\0';
8120
8121                         } else {
8122                                 nested_name = (char *)mod->data;
8123                                 nested_nspace = NULL;
8124                         }
8125
8126                         if (nested_nspace) {
8127                                 if (ignorecase) {
8128                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8129                                                 match = FALSE;
8130                                 } else {
8131                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8132                                                 match = FALSE;
8133                                 }
8134                         }
8135                         if (match) {
8136                                 if (ignorecase) {
8137                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8138                                                 match = FALSE;
8139                                 } else {
8140                                         if (strcmp (klass->name, nested_name) != 0)
8141                                                 match = FALSE;
8142                                 }
8143                         }
8144                         if (lastp) {
8145                                 g_free (nested_name);
8146                                 g_free (nested_nspace);
8147                         }
8148                         if (match)
8149                                 break;
8150                 }
8151
8152                 if (!klass)
8153                         break;
8154         }
8155         if (!klass)
8156                 return NULL;
8157
8158         if (info->type_arguments) {
8159                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8160                 MonoReflectionType *the_type;
8161                 MonoType *instance;
8162                 int i;
8163
8164                 for (i = 0; i < info->type_arguments->len; i++) {
8165                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8166
8167                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8168                         if (!type_args [i]) {
8169                                 g_free (type_args);
8170                                 return NULL;
8171                         }
8172                 }
8173
8174                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8175                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8176
8177                 instance = mono_reflection_bind_generic_parameters (
8178                         the_type, info->type_arguments->len, type_args);
8179
8180                 g_free (type_args);
8181                 if (!instance)
8182                         return NULL;
8183
8184                 klass = mono_class_from_mono_type (instance);
8185         }
8186
8187         for (mod = info->modifiers; mod; mod = mod->next) {
8188                 modval = GPOINTER_TO_UINT (mod->data);
8189                 if (!modval) { /* byref: must be last modifier */
8190                         return &klass->this_arg;
8191                 } else if (modval == -1) {
8192                         klass = mono_ptr_class_get (&klass->byval_arg);
8193                 } else if (modval == -2) {
8194                         bounded = TRUE;
8195                 } else { /* array rank */
8196                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8197                 }
8198         }
8199
8200         return &klass->byval_arg;
8201 }
8202
8203 /*
8204  * mono_reflection_get_type:
8205  * @image: a metadata context
8206  * @info: type description structure
8207  * @ignorecase: flag for case-insensitive string compares
8208  * @type_resolve: whenever type resolve was already tried
8209  *
8210  * Build a MonoType from the type description in @info.
8211  * 
8212  */
8213
8214 MonoType*
8215 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8216         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8217 }
8218
8219 static MonoType*
8220 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8221 {
8222         MonoReflectionAssemblyBuilder *abuilder;
8223         MonoType *type;
8224         int i;
8225
8226         g_assert (assembly_is_dynamic (assembly));
8227         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8228
8229         /* Enumerate all modules */
8230
8231         type = NULL;
8232         if (abuilder->modules) {
8233                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8234                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8235                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8236                         if (type)
8237                                 break;
8238                 }
8239         }
8240
8241         if (!type && abuilder->loaded_modules) {
8242                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8243                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8244                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8245                         if (type)
8246                                 break;
8247                 }
8248         }
8249
8250         return type;
8251 }
8252         
8253 MonoType*
8254 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8255 {
8256         MonoType *type;
8257         MonoReflectionAssembly *assembly;
8258         GString *fullName;
8259         GList *mod;
8260
8261         if (image && image_is_dynamic (image))
8262                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8263         else
8264                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8265         if (type)
8266                 return type;
8267         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8268                 return NULL;
8269
8270         if (type_resolve) {
8271                 if (*type_resolve) 
8272                         return NULL;
8273                 else
8274                         *type_resolve = TRUE;
8275         }
8276         
8277         /* Reconstruct the type name */
8278         fullName = g_string_new ("");
8279         if (info->name_space && (info->name_space [0] != '\0'))
8280                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8281         else
8282                 g_string_printf (fullName, "%s", info->name);
8283         for (mod = info->nested; mod; mod = mod->next)
8284                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8285
8286         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8287         if (assembly) {
8288                 if (assembly_is_dynamic (assembly->assembly))
8289                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8290                 else
8291                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8292                                                                                                           info, ignorecase);
8293         }
8294         g_string_free (fullName, TRUE);
8295         return type;
8296 }
8297
8298 void
8299 mono_reflection_free_type_info (MonoTypeNameParse *info)
8300 {
8301         g_list_free (info->modifiers);
8302         g_list_free (info->nested);
8303
8304         if (info->type_arguments) {
8305                 int i;
8306
8307                 for (i = 0; i < info->type_arguments->len; i++) {
8308                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8309
8310                         mono_reflection_free_type_info (subinfo);
8311                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8312                         g_free (subinfo);
8313                 }
8314
8315                 g_ptr_array_free (info->type_arguments, TRUE);
8316         }
8317 }
8318
8319 /*
8320  * mono_reflection_type_from_name:
8321  * @name: type name.
8322  * @image: a metadata context (can be NULL).
8323  *
8324  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8325  * it defaults to get the type from @image or, if @image is NULL or loading
8326  * from it fails, uses corlib.
8327  * 
8328  */
8329 MonoType*
8330 mono_reflection_type_from_name (char *name, MonoImage *image)
8331 {
8332         MonoType *type = NULL;
8333         MonoTypeNameParse info;
8334         char *tmp;
8335
8336         /* Make a copy since parse_type modifies its argument */
8337         tmp = g_strdup (name);
8338         
8339         /*g_print ("requested type %s\n", str);*/
8340         if (mono_reflection_parse_type (tmp, &info)) {
8341                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8342         }
8343
8344         g_free (tmp);
8345         mono_reflection_free_type_info (&info);
8346         return type;
8347 }
8348
8349 /*
8350  * mono_reflection_get_token:
8351  *
8352  *   Return the metadata token of OBJ which should be an object
8353  * representing a metadata element.
8354  */
8355 guint32
8356 mono_reflection_get_token (MonoObject *obj)
8357 {
8358         MonoClass *klass;
8359         guint32 token = 0;
8360
8361         klass = obj->vtable->klass;
8362
8363         if (strcmp (klass->name, "MethodBuilder") == 0) {
8364                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8365
8366                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8367         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8368                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8369
8370                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8371         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8372                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8373
8374                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8375         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8376                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8377                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8378         } else if (strcmp (klass->name, "MonoType") == 0) {
8379                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8380                 MonoClass *mc = mono_class_from_mono_type (type);
8381                 if (!mono_class_init (mc))
8382                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8383
8384                 token = mc->type_token;
8385         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8386                    strcmp (klass->name, "MonoMethod") == 0 ||
8387                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8388                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8389                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8390                 if (m->method->is_inflated) {
8391                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8392                         return inflated->declaring->token;
8393                 } else {
8394                         token = m->method->token;
8395                 }
8396         } else if (strcmp (klass->name, "MonoField") == 0) {
8397                 MonoReflectionField *f = (MonoReflectionField*)obj;
8398
8399                 if (is_field_on_inst (f->field)) {
8400                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8401
8402                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8403                                 int field_index = f->field - dgclass->fields;
8404                                 MonoObject *obj;
8405
8406                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8407                                 obj = dgclass->field_objects [field_index];
8408                                 return mono_reflection_get_token (obj);
8409                         }
8410                 }
8411                 token = mono_class_get_field_token (f->field);
8412         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8413                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8414
8415                 token = mono_class_get_property_token (p->property);
8416         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8417                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8418
8419                 token = mono_class_get_event_token (p->event);
8420         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8421                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8422                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8423                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8424
8425                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8426         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8427                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8428
8429                 token = m->token;
8430         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8431                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8432         } else {
8433                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8434                 MonoException *ex = mono_get_exception_not_implemented (msg);
8435                 g_free (msg);
8436                 mono_raise_exception (ex);
8437         }
8438
8439         return token;
8440 }
8441
8442 static MonoClass*
8443 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8444 {
8445         char *n;
8446         MonoType *t;
8447         int slen = mono_metadata_decode_value (p, &p);
8448
8449         mono_error_init (error);
8450
8451         n = (char *)g_memdup (p, slen + 1);
8452         n [slen] = 0;
8453         t = mono_reflection_type_from_name (n, image);
8454         if (!t) {
8455                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8456                 /* We don't free n, it's consumed by mono_error */
8457                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8458                 return NULL;
8459         }
8460         g_free (n);
8461         p += slen;
8462         *end = p;
8463         return mono_class_from_mono_type (t);
8464 }
8465
8466 static void*
8467 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8468 {
8469         int slen, type = t->type;
8470         MonoClass *tklass = t->data.klass;
8471
8472         mono_error_init (error);
8473
8474 handle_enum:
8475         switch (type) {
8476         case MONO_TYPE_U1:
8477         case MONO_TYPE_I1:
8478         case MONO_TYPE_BOOLEAN: {
8479                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8480                 *bval = *p;
8481                 *end = p + 1;
8482                 return bval;
8483         }
8484         case MONO_TYPE_CHAR:
8485         case MONO_TYPE_U2:
8486         case MONO_TYPE_I2: {
8487                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8488                 *val = read16 (p);
8489                 *end = p + 2;
8490                 return val;
8491         }
8492 #if SIZEOF_VOID_P == 4
8493         case MONO_TYPE_U:
8494         case MONO_TYPE_I:
8495 #endif
8496         case MONO_TYPE_R4:
8497         case MONO_TYPE_U4:
8498         case MONO_TYPE_I4: {
8499                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8500                 *val = read32 (p);
8501                 *end = p + 4;
8502                 return val;
8503         }
8504 #if SIZEOF_VOID_P == 8
8505         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8506         case MONO_TYPE_I:
8507 #endif
8508         case MONO_TYPE_U8:
8509         case MONO_TYPE_I8: {
8510                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8511                 *val = read64 (p);
8512                 *end = p + 8;
8513                 return val;
8514         }
8515         case MONO_TYPE_R8: {
8516                 double *val = (double *)g_malloc (sizeof (double));
8517                 readr8 (p, val);
8518                 *end = p + 8;
8519                 return val;
8520         }
8521         case MONO_TYPE_VALUETYPE:
8522                 if (t->data.klass->enumtype) {
8523                         type = mono_class_enum_basetype (t->data.klass)->type;
8524                         goto handle_enum;
8525                 } else {
8526                         MonoClass *k =  t->data.klass;
8527                         
8528                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8529                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8530                                 *val = read64 (p);
8531                                 *end = p + 8;
8532                                 return val;
8533                         }
8534                 }
8535                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8536                 break;
8537                 
8538         case MONO_TYPE_STRING:
8539                 if (*p == (char)0xFF) {
8540                         *end = p + 1;
8541                         return NULL;
8542                 }
8543                 slen = mono_metadata_decode_value (p, &p);
8544                 *end = p + slen;
8545                 return mono_string_new_len (mono_domain_get (), p, slen);
8546         case MONO_TYPE_CLASS: {
8547                 MonoReflectionType *rt;
8548                 char *n;
8549                 MonoType *t;
8550                 if (*p == (char)0xFF) {
8551                         *end = p + 1;
8552                         return NULL;
8553                 }
8554 handle_type:
8555                 slen = mono_metadata_decode_value (p, &p);
8556                 n = (char *)g_memdup (p, slen + 1);
8557                 n [slen] = 0;
8558                 t = mono_reflection_type_from_name (n, image);
8559                 if (!t) {
8560                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8561                         /* We don't free n, it's consumed by mono_error */
8562                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8563                         return NULL;
8564                 }
8565                 g_free (n);
8566                 *end = p + slen;
8567
8568                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8569                 if (!mono_error_ok (error))
8570                         return NULL;
8571
8572                 return rt;
8573         }
8574         case MONO_TYPE_OBJECT: {
8575                 char subt = *p++;
8576                 MonoObject *obj;
8577                 MonoClass *subc = NULL;
8578                 void *val;
8579
8580                 if (subt == 0x50) {
8581                         goto handle_type;
8582                 } else if (subt == 0x0E) {
8583                         type = MONO_TYPE_STRING;
8584                         goto handle_enum;
8585                 } else if (subt == 0x1D) {
8586                         MonoType simple_type = {{0}};
8587                         int etype = *p;
8588                         p ++;
8589
8590                         type = MONO_TYPE_SZARRAY;
8591                         if (etype == 0x50) {
8592                                 tklass = mono_defaults.systemtype_class;
8593                         } else if (etype == 0x55) {
8594                                 tklass = load_cattr_enum_type (image, p, &p, error);
8595                                 if (!mono_error_ok (error))
8596                                         return NULL;
8597                         } else {
8598                                 if (etype == 0x51)
8599                                         /* See Partition II, Appendix B3 */
8600                                         etype = MONO_TYPE_OBJECT;
8601                                 simple_type.type = (MonoTypeEnum)etype;
8602                                 tklass = mono_class_from_mono_type (&simple_type);
8603                         }
8604                         goto handle_enum;
8605                 } else if (subt == 0x55) {
8606                         char *n;
8607                         MonoType *t;
8608                         slen = mono_metadata_decode_value (p, &p);
8609                         n = (char *)g_memdup (p, slen + 1);
8610                         n [slen] = 0;
8611                         t = mono_reflection_type_from_name (n, image);
8612                         if (!t) {
8613                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8614                                 /* We don't free n, it's consumed by mono_error */
8615                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8616                                 return NULL;
8617                         }
8618                         g_free (n);
8619                         p += slen;
8620                         subc = mono_class_from_mono_type (t);
8621                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8622                         MonoType simple_type = {{0}};
8623                         simple_type.type = (MonoTypeEnum)subt;
8624                         subc = mono_class_from_mono_type (&simple_type);
8625                 } else {
8626                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8627                 }
8628                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8629                 obj = NULL;
8630                 if (mono_error_ok (error)) {
8631                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8632                         g_assert (!subc->has_references);
8633                         if (mono_error_ok (error))
8634                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8635                 }
8636
8637                 g_free (val);
8638                 return obj;
8639         }
8640         case MONO_TYPE_SZARRAY: {
8641                 MonoArray *arr;
8642                 guint32 i, alen, basetype;
8643                 alen = read32 (p);
8644                 p += 4;
8645                 if (alen == 0xffffffff) {
8646                         *end = p;
8647                         return NULL;
8648                 }
8649                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8650                 basetype = tklass->byval_arg.type;
8651                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8652                         basetype = mono_class_enum_basetype (tklass)->type;
8653                 switch (basetype)
8654                 {
8655                         case MONO_TYPE_U1:
8656                         case MONO_TYPE_I1:
8657                         case MONO_TYPE_BOOLEAN:
8658                                 for (i = 0; i < alen; i++) {
8659                                         MonoBoolean val = *p++;
8660                                         mono_array_set (arr, MonoBoolean, i, val);
8661                                 }
8662                                 break;
8663                         case MONO_TYPE_CHAR:
8664                         case MONO_TYPE_U2:
8665                         case MONO_TYPE_I2:
8666                                 for (i = 0; i < alen; i++) {
8667                                         guint16 val = read16 (p);
8668                                         mono_array_set (arr, guint16, i, val);
8669                                         p += 2;
8670                                 }
8671                                 break;
8672                         case MONO_TYPE_R4:
8673                         case MONO_TYPE_U4:
8674                         case MONO_TYPE_I4:
8675                                 for (i = 0; i < alen; i++) {
8676                                         guint32 val = read32 (p);
8677                                         mono_array_set (arr, guint32, i, val);
8678                                         p += 4;
8679                                 }
8680                                 break;
8681                         case MONO_TYPE_R8:
8682                                 for (i = 0; i < alen; i++) {
8683                                         double val;
8684                                         readr8 (p, &val);
8685                                         mono_array_set (arr, double, i, val);
8686                                         p += 8;
8687                                 }
8688                                 break;
8689                         case MONO_TYPE_U8:
8690                         case MONO_TYPE_I8:
8691                                 for (i = 0; i < alen; i++) {
8692                                         guint64 val = read64 (p);
8693                                         mono_array_set (arr, guint64, i, val);
8694                                         p += 8;
8695                                 }
8696                                 break;
8697                         case MONO_TYPE_CLASS:
8698                         case MONO_TYPE_OBJECT:
8699                         case MONO_TYPE_STRING:
8700                         case MONO_TYPE_SZARRAY:
8701                                 for (i = 0; i < alen; i++) {
8702                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8703                                         if (!mono_error_ok (error))
8704                                                 return NULL;
8705                                         mono_array_setref (arr, i, item);
8706                                 }
8707                                 break;
8708                         default:
8709                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8710                 }
8711                 *end=p;
8712                 return arr;
8713         }
8714         default:
8715                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8716         }
8717         return NULL;
8718 }
8719
8720 static MonoObject*
8721 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8722 {
8723         static MonoClass *klass;
8724         static MonoMethod *ctor;
8725         MonoError error;
8726         MonoObject *retval;
8727         void *params [2], *unboxed;
8728
8729         if (!klass)
8730                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8731         if (!ctor)
8732                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8733         
8734         params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8735         mono_error_raise_exception (&error); /* FIXME don't raise here */
8736
8737         params [1] = val;
8738         retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8739         mono_error_raise_exception (&error); /* FIXME don't raise here */
8740         unboxed = mono_object_unbox (retval);
8741         mono_runtime_invoke (ctor, unboxed, params, NULL);
8742
8743         return retval;
8744 }
8745
8746 static MonoObject*
8747 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8748 {
8749         static MonoClass *klass;
8750         static MonoMethod *ctor;
8751         MonoError error;
8752         MonoObject *retval;
8753         void *unboxed, *params [2];
8754
8755         if (!klass)
8756                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8757         if (!ctor)
8758                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8759
8760         params [0] = minfo;
8761         params [1] = typedarg;
8762         retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8763         mono_error_raise_exception (&error); /* FIXME don't raise here */
8764         unboxed = mono_object_unbox (retval);
8765         mono_runtime_invoke (ctor, unboxed, params, NULL);
8766
8767         return retval;
8768 }
8769
8770 static gboolean
8771 type_is_reference (MonoType *type)
8772 {
8773         switch (type->type) {
8774         case MONO_TYPE_BOOLEAN:
8775         case MONO_TYPE_CHAR:
8776         case MONO_TYPE_U:
8777         case MONO_TYPE_I:
8778         case MONO_TYPE_U1:
8779         case MONO_TYPE_I1:
8780         case MONO_TYPE_U2:
8781         case MONO_TYPE_I2:
8782         case MONO_TYPE_U4:
8783         case MONO_TYPE_I4:
8784         case MONO_TYPE_U8:
8785         case MONO_TYPE_I8:
8786         case MONO_TYPE_R8:
8787         case MONO_TYPE_R4:
8788         case MONO_TYPE_VALUETYPE:
8789                 return FALSE;
8790         default:
8791                 return TRUE;
8792         }
8793 }
8794
8795 static void
8796 free_param_data (MonoMethodSignature *sig, void **params) {
8797         int i;
8798         for (i = 0; i < sig->param_count; ++i) {
8799                 if (!type_is_reference (sig->params [i]))
8800                         g_free (params [i]);
8801         }
8802 }
8803
8804 /*
8805  * Find the field index in the metadata FieldDef table.
8806  */
8807 static guint32
8808 find_field_index (MonoClass *klass, MonoClassField *field) {
8809         int i;
8810
8811         for (i = 0; i < klass->field.count; ++i) {
8812                 if (field == &klass->fields [i])
8813                         return klass->field.first + 1 + i;
8814         }
8815         return 0;
8816 }
8817
8818 /*
8819  * Find the property index in the metadata Property table.
8820  */
8821 static guint32
8822 find_property_index (MonoClass *klass, MonoProperty *property) {
8823         int i;
8824
8825         for (i = 0; i < klass->ext->property.count; ++i) {
8826                 if (property == &klass->ext->properties [i])
8827                         return klass->ext->property.first + 1 + i;
8828         }
8829         return 0;
8830 }
8831
8832 /*
8833  * Find the event index in the metadata Event table.
8834  */
8835 static guint32
8836 find_event_index (MonoClass *klass, MonoEvent *event) {
8837         int i;
8838
8839         for (i = 0; i < klass->ext->event.count; ++i) {
8840                 if (event == &klass->ext->events [i])
8841                         return klass->ext->event.first + 1 + i;
8842         }
8843         return 0;
8844 }
8845
8846 static MonoObject*
8847 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8848 {
8849         const char *p = (const char*)data;
8850         const char *named;
8851         guint32 i, j, num_named;
8852         MonoObject *attr;
8853         void *params_buf [32];
8854         void **params = NULL;
8855         MonoMethodSignature *sig;
8856         MonoObject *exc = NULL;
8857
8858         mono_error_init (error);
8859
8860         mono_class_init (method->klass);
8861
8862         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8863                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8864                 return NULL;
8865         }
8866
8867         if (len == 0) {
8868                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8869                 if (!mono_error_ok (error)) return NULL;
8870                 mono_runtime_invoke (method, attr, NULL, NULL);
8871                 return attr;
8872         }
8873
8874         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8875                 return NULL;
8876
8877         /*g_print ("got attr %s\n", method->klass->name);*/
8878
8879         sig = mono_method_signature (method);
8880         if (sig->param_count < 32) {
8881                 params = params_buf;
8882                 memset (params, 0, sizeof (void*) * sig->param_count);
8883         } else {
8884                 /* Allocate using GC so it gets GC tracking */
8885                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8886         }
8887
8888         /* skip prolog */
8889         p += 2;
8890         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8891                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8892                 if (!mono_error_ok (error))
8893                         goto fail;
8894         }
8895
8896         named = p;
8897         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8898         if (!mono_error_ok (error)) goto fail;
8899
8900         mono_runtime_invoke (method, attr, params, &exc);
8901         if (exc)
8902                 goto fail;
8903         num_named = read16 (named);
8904         named += 2;
8905         for (j = 0; j < num_named; j++) {
8906                 gint name_len;
8907                 char *name, named_type, data_type;
8908                 named_type = *named++;
8909                 data_type = *named++; /* type of data */
8910                 if (data_type == MONO_TYPE_SZARRAY)
8911                         data_type = *named++;
8912                 if (data_type == MONO_TYPE_ENUM) {
8913                         gint type_len;
8914                         char *type_name;
8915                         type_len = mono_metadata_decode_blob_size (named, &named);
8916                         type_name = (char *)g_malloc (type_len + 1);
8917                         memcpy (type_name, named, type_len);
8918                         type_name [type_len] = 0;
8919                         named += type_len;
8920                         /* FIXME: lookup the type and check type consistency */
8921                         g_free (type_name);
8922                 }
8923                 name_len = mono_metadata_decode_blob_size (named, &named);
8924                 name = (char *)g_malloc (name_len + 1);
8925                 memcpy (name, named, name_len);
8926                 name [name_len] = 0;
8927                 named += name_len;
8928                 if (named_type == 0x53) {
8929                         MonoClassField *field;
8930                         void *val;
8931
8932                         /* how this fail is a blackbox */
8933                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8934                         if (!field) {
8935                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8936                                 g_free (name);
8937                                 goto fail;
8938                         }
8939
8940                         val = load_cattr_value (image, field->type, named, &named, error);
8941                         if (!mono_error_ok (error)) {
8942                                 g_free (name);
8943                                 if (!type_is_reference (field->type))
8944                                         g_free (val);
8945                                 goto fail;
8946                         }
8947
8948                         mono_field_set_value (attr, field, val);
8949                         if (!type_is_reference (field->type))
8950                                 g_free (val);
8951                 } else if (named_type == 0x54) {
8952                         MonoProperty *prop;
8953                         void *pparams [1];
8954                         MonoType *prop_type;
8955
8956                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8957
8958                         if (!prop) {
8959                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8960                                 g_free (name);
8961                                 goto fail;
8962                         }
8963
8964                         if (!prop->set) {
8965                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8966                                 g_free (name);
8967                                 goto fail;
8968                         }
8969
8970                         /* can we have more that 1 arg in a custom attr named property? */
8971                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8972                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8973
8974                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8975                         if (!mono_error_ok (error)) {
8976                                 g_free (name);
8977                                 if (!type_is_reference (prop_type))
8978                                         g_free (pparams [0]);
8979                                 goto fail;
8980                         }
8981
8982
8983                         mono_property_set_value (prop, attr, pparams, NULL);
8984                         if (!type_is_reference (prop_type))
8985                                 g_free (pparams [0]);
8986                 }
8987                 g_free (name);
8988         }
8989
8990         free_param_data (method->signature, params);
8991         if (params != params_buf)
8992                 mono_gc_free_fixed (params);
8993
8994         return attr;
8995
8996 fail:
8997         free_param_data (method->signature, params);
8998         if (params != params_buf)
8999                 mono_gc_free_fixed (params);
9000         if (exc)
9001                 mono_raise_exception ((MonoException*)exc);
9002         return NULL;
9003 }
9004         
9005 /*
9006  * mono_reflection_create_custom_attr_data_args:
9007  *
9008  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9009  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9010  * NAMED_ARG_INFO will contain information about the named arguments.
9011  */
9012 void
9013 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
9014 {
9015         MonoArray *typedargs, *namedargs;
9016         MonoClass *attrklass;
9017         MonoDomain *domain;
9018         const char *p = (const char*)data;
9019         const char *named;
9020         guint32 i, j, num_named;
9021         CattrNamedArg *arginfo = NULL;
9022
9023         *typed_args = NULL;
9024         *named_args = NULL;
9025         *named_arg_info = NULL;
9026
9027         mono_error_init (error);
9028
9029         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9030                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9031                 return;
9032         }
9033
9034         mono_class_init (method->klass);
9035         
9036         domain = mono_domain_get ();
9037
9038         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9039                 return;
9040
9041         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9042         
9043         /* skip prolog */
9044         p += 2;
9045         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9046                 MonoObject *obj;
9047                 void *val;
9048
9049                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9050                 if (!mono_error_ok (error)) {
9051                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9052                                 g_free (val);
9053                         return;
9054                 }
9055
9056                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9057                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9058                 mono_array_setref (typedargs, i, obj);
9059
9060                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9061                         g_free (val);
9062         }
9063
9064         named = p;
9065         num_named = read16 (named);
9066         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9067         named += 2;
9068         attrklass = method->klass;
9069
9070         arginfo = g_new0 (CattrNamedArg, num_named);
9071         *named_arg_info = arginfo;
9072
9073         for (j = 0; j < num_named; j++) {
9074                 gint name_len;
9075                 char *name, named_type, data_type;
9076                 named_type = *named++;
9077                 data_type = *named++; /* type of data */
9078                 if (data_type == MONO_TYPE_SZARRAY)
9079                         data_type = *named++;
9080                 if (data_type == MONO_TYPE_ENUM) {
9081                         gint type_len;
9082                         char *type_name;
9083                         type_len = mono_metadata_decode_blob_size (named, &named);
9084                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9085                                 goto fail;
9086
9087                         type_name = (char *)g_malloc (type_len + 1);
9088                         memcpy (type_name, named, type_len);
9089                         type_name [type_len] = 0;
9090                         named += type_len;
9091                         /* FIXME: lookup the type and check type consistency */
9092                         g_free (type_name);
9093                 }
9094                 name_len = mono_metadata_decode_blob_size (named, &named);
9095                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9096                         goto fail;
9097                 name = (char *)g_malloc (name_len + 1);
9098                 memcpy (name, named, name_len);
9099                 name [name_len] = 0;
9100                 named += name_len;
9101                 if (named_type == 0x53) {
9102                         MonoObject *obj;
9103                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9104                         void *val;
9105
9106                         if (!field) {
9107                                 g_free (name);
9108                                 goto fail;
9109                         }
9110
9111                         arginfo [j].type = field->type;
9112                         arginfo [j].field = field;
9113
9114                         val = load_cattr_value (image, field->type, named, &named, error);
9115                         if (!mono_error_ok (error)) {
9116                                 if (!type_is_reference (field->type))
9117                                         g_free (val);
9118                                 g_free (name);
9119                                 return;
9120                         }
9121
9122                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9123                         mono_array_setref (namedargs, j, obj);
9124                         if (!type_is_reference (field->type))
9125                                 g_free (val);
9126                 } else if (named_type == 0x54) {
9127                         MonoObject *obj;
9128                         MonoType *prop_type;
9129                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9130                         void *val;
9131
9132                         if (!prop || !prop->set) {
9133                                 g_free (name);
9134                                 goto fail;
9135                         }
9136
9137                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9138                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9139
9140                         arginfo [j].type = prop_type;
9141                         arginfo [j].prop = prop;
9142
9143                         val = load_cattr_value (image, prop_type, named, &named, error);
9144                         if (!mono_error_ok (error)) {
9145                                 if (!type_is_reference (prop_type))
9146                                         g_free (val);
9147                                 g_free (name);
9148                                 return;
9149                         }
9150
9151                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9152                         mono_array_setref (namedargs, j, obj);
9153                         if (!type_is_reference (prop_type))
9154                                 g_free (val);
9155                 }
9156                 g_free (name);
9157         }
9158
9159         *typed_args = typedargs;
9160         *named_args = namedargs;
9161         return;
9162 fail:
9163         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9164         g_free (arginfo);
9165         *named_arg_info = NULL;
9166 }
9167
9168 void
9169 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9170 {
9171         MonoDomain *domain;
9172         MonoArray *typedargs, *namedargs;
9173         MonoImage *image;
9174         MonoMethod *method;
9175         CattrNamedArg *arginfo = NULL;
9176         MonoError error;
9177         int i;
9178
9179         mono_error_init (&error);
9180
9181         *ctor_args = NULL;
9182         *named_args = NULL;
9183
9184         if (len == 0)
9185                 return;
9186
9187         image = assembly->assembly->image;
9188         method = ref_method->method;
9189         domain = mono_object_domain (ref_method);
9190
9191         if (!mono_class_init (method->klass))
9192                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9193
9194         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9195         if (!mono_error_ok (&error))
9196                 goto leave;
9197
9198         if (mono_loader_get_last_error ()) {
9199                 mono_error_set_from_loader_error (&error);
9200                 goto leave;
9201         }
9202
9203         if (!typedargs || !namedargs)
9204                 goto leave;
9205
9206         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9207                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9208                 MonoObject *typedarg;
9209
9210                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9211                 mono_array_setref (typedargs, i, typedarg);
9212         }
9213
9214         for (i = 0; i < mono_array_length (namedargs); ++i) {
9215                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9216                 MonoObject *typedarg, *namedarg, *minfo;
9217
9218                 if (arginfo [i].prop)
9219                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9220                 else {
9221                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9222                         if (!mono_error_ok (&error))
9223                                 goto leave;
9224                 }
9225
9226                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9227                 namedarg = create_cattr_named_arg (minfo, typedarg);
9228
9229                 mono_array_setref (namedargs, i, namedarg);
9230         }
9231
9232         *ctor_args = typedargs;
9233         *named_args = namedargs;
9234 leave:
9235         g_free (arginfo);
9236         mono_error_raise_exception (&error);
9237
9238 }
9239
9240 static MonoObject*
9241 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9242 {
9243         static MonoMethod *ctor;
9244
9245         MonoError error;
9246         MonoDomain *domain;
9247         MonoObject *attr;
9248         void *params [4];
9249
9250         g_assert (image->assembly);
9251
9252         if (!ctor)
9253                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9254
9255         domain = mono_domain_get ();
9256         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9257         mono_error_raise_exception (&error); /* FIXME don't raise here */
9258         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9259         mono_error_raise_exception (&error); /* FIXME don't raise here */
9260         params [1] = mono_assembly_get_object (domain, image->assembly);
9261         params [2] = (gpointer)&cattr->data;
9262         params [3] = &cattr->data_size;
9263         mono_runtime_invoke (ctor, attr, params, NULL);
9264         return attr;
9265 }
9266
9267 static MonoArray*
9268 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9269 {
9270         MonoArray *result;
9271         MonoObject *attr;
9272         int i, n;
9273
9274         mono_error_init (error);
9275
9276         n = 0;
9277         for (i = 0; i < cinfo->num_attrs; ++i) {
9278                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9279                         n ++;
9280         }
9281
9282         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9283         n = 0;
9284         for (i = 0; i < cinfo->num_attrs; ++i) {
9285                 if (!cinfo->attrs [i].ctor)
9286                         /* The cattr type is not finished yet */
9287                         /* We should include the type name but cinfo doesn't contain it */
9288                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9289                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9290                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9291                         if (!mono_error_ok (error))
9292                                 return result;
9293                         mono_array_setref (result, n, attr);
9294                         n ++;
9295                 }
9296         }
9297         return result;
9298 }
9299
9300 MonoArray*
9301 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9302 {
9303         MonoError error;
9304         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9305         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9306
9307         return result;
9308 }
9309
9310 static MonoArray*
9311 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9312 {
9313         MonoArray *result;
9314         MonoObject *attr;
9315         int i;
9316         
9317         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9318         for (i = 0; i < cinfo->num_attrs; ++i) {
9319                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9320                 mono_array_setref (result, i, attr);
9321         }
9322         return result;
9323 }
9324
9325 /**
9326  * mono_custom_attrs_from_index:
9327  *
9328  * Returns: NULL if no attributes are found or if a loading error occurs.
9329  */
9330 MonoCustomAttrInfo*
9331 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9332 {
9333         guint32 mtoken, i, len;
9334         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9335         MonoTableInfo *ca;
9336         MonoCustomAttrInfo *ainfo;
9337         GList *tmp, *list = NULL;
9338         const char *data;
9339         MonoCustomAttrEntry* attr;
9340
9341         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9342
9343         i = mono_metadata_custom_attrs_from_index (image, idx);
9344         if (!i)
9345                 return NULL;
9346         i --;
9347         while (i < ca->rows) {
9348                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9349                         break;
9350                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9351                 ++i;
9352         }
9353         len = g_list_length (list);
9354         if (!len)
9355                 return NULL;
9356         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9357         ainfo->num_attrs = len;
9358         ainfo->image = image;
9359         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9360                 MonoError error;
9361                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9362                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9363                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9364                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9365                         mtoken |= MONO_TOKEN_METHOD_DEF;
9366                         break;
9367                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9368                         mtoken |= MONO_TOKEN_MEMBER_REF;
9369                         break;
9370                 default:
9371                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9372                         break;
9373                 }
9374                 attr = &ainfo->attrs [i - 1];
9375                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9376                 if (!attr->ctor) {
9377                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9378                         mono_loader_set_error_from_mono_error (&error);
9379                         g_list_free (list);
9380                         g_free (ainfo);
9381                         return NULL;
9382                 }
9383
9384                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9385                         /*FIXME raising an exception here doesn't make any sense*/
9386                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9387                         g_list_free (list);
9388                         g_free (ainfo);
9389                         return NULL;
9390                 }
9391                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9392                 attr->data_size = mono_metadata_decode_value (data, &data);
9393                 attr->data = (guchar*)data;
9394         }
9395         g_list_free (list);
9396
9397         return ainfo;
9398 }
9399
9400 MonoCustomAttrInfo*
9401 mono_custom_attrs_from_method (MonoMethod *method)
9402 {
9403         guint32 idx;
9404
9405         /*
9406          * An instantiated method has the same cattrs as the generic method definition.
9407          *
9408          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9409          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9410          */
9411         if (method->is_inflated)
9412                 method = ((MonoMethodInflated *) method)->declaring;
9413         
9414         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9415                 return lookup_custom_attr (method->klass->image, method);
9416
9417         if (!method->token)
9418                 /* Synthetic methods */
9419                 return NULL;
9420
9421         idx = mono_method_get_index (method);
9422         idx <<= MONO_CUSTOM_ATTR_BITS;
9423         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9424         return mono_custom_attrs_from_index (method->klass->image, idx);
9425 }
9426
9427 MonoCustomAttrInfo*
9428 mono_custom_attrs_from_class (MonoClass *klass)
9429 {
9430         guint32 idx;
9431
9432         if (klass->generic_class)
9433                 klass = klass->generic_class->container_class;
9434
9435         if (image_is_dynamic (klass->image))
9436                 return lookup_custom_attr (klass->image, klass);
9437
9438         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9439                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9440                 idx <<= MONO_CUSTOM_ATTR_BITS;
9441                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9442         } else {
9443                 idx = mono_metadata_token_index (klass->type_token);
9444                 idx <<= MONO_CUSTOM_ATTR_BITS;
9445                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9446         }
9447         return mono_custom_attrs_from_index (klass->image, idx);
9448 }
9449
9450 MonoCustomAttrInfo*
9451 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9452 {
9453         guint32 idx;
9454         
9455         if (image_is_dynamic (assembly->image))
9456                 return lookup_custom_attr (assembly->image, assembly);
9457         idx = 1; /* there is only one assembly */
9458         idx <<= MONO_CUSTOM_ATTR_BITS;
9459         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9460         return mono_custom_attrs_from_index (assembly->image, idx);
9461 }
9462
9463 static MonoCustomAttrInfo*
9464 mono_custom_attrs_from_module (MonoImage *image)
9465 {
9466         guint32 idx;
9467         
9468         if (image_is_dynamic (image))
9469                 return lookup_custom_attr (image, image);
9470         idx = 1; /* there is only one module */
9471         idx <<= MONO_CUSTOM_ATTR_BITS;
9472         idx |= MONO_CUSTOM_ATTR_MODULE;
9473         return mono_custom_attrs_from_index (image, idx);
9474 }
9475
9476 MonoCustomAttrInfo*
9477 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9478 {
9479         guint32 idx;
9480         
9481         if (image_is_dynamic (klass->image)) {
9482                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9483                 return lookup_custom_attr (klass->image, property);
9484         }
9485         idx = find_property_index (klass, property);
9486         idx <<= MONO_CUSTOM_ATTR_BITS;
9487         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9488         return mono_custom_attrs_from_index (klass->image, idx);
9489 }
9490
9491 MonoCustomAttrInfo*
9492 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9493 {
9494         guint32 idx;
9495         
9496         if (image_is_dynamic (klass->image)) {
9497                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9498                 return lookup_custom_attr (klass->image, event);
9499         }
9500         idx = find_event_index (klass, event);
9501         idx <<= MONO_CUSTOM_ATTR_BITS;
9502         idx |= MONO_CUSTOM_ATTR_EVENT;
9503         return mono_custom_attrs_from_index (klass->image, idx);
9504 }
9505
9506 MonoCustomAttrInfo*
9507 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9508 {
9509         guint32 idx;
9510         if (image_is_dynamic (klass->image)) {
9511                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9512                 return lookup_custom_attr (klass->image, field);
9513         }
9514         idx = find_field_index (klass, field);
9515         idx <<= MONO_CUSTOM_ATTR_BITS;
9516         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9517         return mono_custom_attrs_from_index (klass->image, idx);
9518 }
9519
9520 /**
9521  * mono_custom_attrs_from_param:
9522  * @method: handle to the method that we want to retrieve custom parameter information from
9523  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9524  *
9525  * The result must be released with mono_custom_attrs_free().
9526  *
9527  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9528  */
9529 MonoCustomAttrInfo*
9530 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9531 {
9532         MonoTableInfo *ca;
9533         guint32 i, idx, method_index;
9534         guint32 param_list, param_last, param_pos, found;
9535         MonoImage *image;
9536         MonoReflectionMethodAux *aux;
9537
9538         /*
9539          * An instantiated method has the same cattrs as the generic method definition.
9540          *
9541          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9542          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9543          */
9544         if (method->is_inflated)
9545                 method = ((MonoMethodInflated *) method)->declaring;
9546
9547         if (image_is_dynamic (method->klass->image)) {
9548                 MonoCustomAttrInfo *res, *ainfo;
9549                 int size;
9550
9551                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9552                 if (!aux || !aux->param_cattr)
9553                         return NULL;
9554
9555                 /* Need to copy since it will be freed later */
9556                 ainfo = aux->param_cattr [param];
9557                 if (!ainfo)
9558                         return NULL;
9559                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9560                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9561                 memcpy (res, ainfo, size);
9562                 return res;
9563         }
9564
9565         image = method->klass->image;
9566         method_index = mono_method_get_index (method);
9567         if (!method_index)
9568                 return NULL;
9569         ca = &image->tables [MONO_TABLE_METHOD];
9570
9571         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9572         if (method_index == ca->rows) {
9573                 ca = &image->tables [MONO_TABLE_PARAM];
9574                 param_last = ca->rows + 1;
9575         } else {
9576                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9577                 ca = &image->tables [MONO_TABLE_PARAM];
9578         }
9579         found = FALSE;
9580         for (i = param_list; i < param_last; ++i) {
9581                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9582                 if (param_pos == param) {
9583                         found = TRUE;
9584                         break;
9585                 }
9586         }
9587         if (!found)
9588                 return NULL;
9589         idx = i;
9590         idx <<= MONO_CUSTOM_ATTR_BITS;
9591         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9592         return mono_custom_attrs_from_index (image, idx);
9593 }
9594
9595 gboolean
9596 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9597 {
9598         int i;
9599         MonoClass *klass;
9600         for (i = 0; i < ainfo->num_attrs; ++i) {
9601                 klass = ainfo->attrs [i].ctor->klass;
9602                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9603                         return TRUE;
9604         }
9605         return FALSE;
9606 }
9607
9608 MonoObject*
9609 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9610 {
9611         MonoError error;
9612         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9613         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9614         return res;
9615 }
9616
9617 MonoObject*
9618 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9619 {
9620         int i, attr_index;
9621         MonoClass *klass;
9622         MonoArray *attrs;
9623
9624         mono_error_init (error);
9625
9626         attr_index = -1;
9627         for (i = 0; i < ainfo->num_attrs; ++i) {
9628                 klass = ainfo->attrs [i].ctor->klass;
9629                 if (mono_class_has_parent (klass, attr_klass)) {
9630                         attr_index = i;
9631                         break;
9632                 }
9633         }
9634         if (attr_index == -1)
9635                 return NULL;
9636
9637         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9638         if (!mono_error_ok (error))
9639                 return NULL;
9640         return mono_array_get (attrs, MonoObject*, attr_index);
9641 }
9642
9643 /*
9644  * mono_reflection_get_custom_attrs_info:
9645  * @obj: a reflection object handle
9646  *
9647  * Return the custom attribute info for attributes defined for the
9648  * reflection handle @obj. The objects.
9649  *
9650  * FIXME this function leaks like a sieve for SRE objects.
9651  */
9652 MonoCustomAttrInfo*
9653 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9654 {
9655         MonoClass *klass;
9656         MonoCustomAttrInfo *cinfo = NULL;
9657         
9658         klass = obj->vtable->klass;
9659         if (klass == mono_defaults.monotype_class) {
9660                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9661                 klass = mono_class_from_mono_type (type);
9662                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9663                 cinfo = mono_custom_attrs_from_class (klass);
9664         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9665                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9666                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9667         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9668                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9669                 cinfo = mono_custom_attrs_from_module (module->image);
9670         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9671                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9672                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9673         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9674                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9675                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9676         } else if (strcmp ("MonoField", klass->name) == 0) {
9677                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9678                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9679         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9680                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9681                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9682         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9683                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9684                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9685         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9686                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9687                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9688                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9689                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9690                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9691                 } else if (is_sr_mono_property (member_class)) {
9692                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9693                         MonoMethod *method;
9694                         if (!(method = prop->property->get))
9695                                 method = prop->property->set;
9696                         g_assert (method);
9697
9698                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9699                 } 
9700 #ifndef DISABLE_REFLECTION_EMIT
9701                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9702                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9703                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9704                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9705                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9706                         MonoMethod *method = NULL;
9707                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9708                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9709                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9710                                 method = ((MonoReflectionMethod *)c->cb)->method;
9711                         else
9712                                 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));
9713
9714                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9715                 } 
9716 #endif
9717                 else {
9718                         char *type_name = mono_type_get_full_name (member_class);
9719                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9720                         MonoException *ex = mono_get_exception_not_supported  (msg);
9721                         g_free (type_name);
9722                         g_free (msg);
9723                         mono_raise_exception (ex);
9724                 }
9725         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9726                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9727                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9728         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9729                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9730                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9731         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9732                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9733                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9734         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9735                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9736                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9737         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9738                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9739                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9740         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9741                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9742                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9743         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9744                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9745                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9746         } else { /* handle other types here... */
9747                 g_error ("get custom attrs not yet supported for %s", klass->name);
9748         }
9749
9750         return cinfo;
9751 }
9752
9753 /*
9754  * mono_reflection_get_custom_attrs_by_type:
9755  * @obj: a reflection object handle
9756  *
9757  * Return an array with all the custom attributes defined of the
9758  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9759  * of that type are returned. The objects are fully build. Return NULL if a loading error
9760  * occurs.
9761  */
9762 MonoArray*
9763 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9764 {
9765         MonoArray *result;
9766         MonoCustomAttrInfo *cinfo;
9767
9768         mono_error_init (error);
9769
9770         cinfo = mono_reflection_get_custom_attrs_info (obj);
9771         if (cinfo) {
9772                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9773                 if (!cinfo->cached)
9774                         mono_custom_attrs_free (cinfo);
9775         } else {
9776                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9777                 if (mono_loader_get_last_error ())
9778                         return NULL;
9779                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9780         }
9781
9782         return result;
9783 }
9784
9785 /*
9786  * mono_reflection_get_custom_attrs:
9787  * @obj: a reflection object handle
9788  *
9789  * Return an array with all the custom attributes defined of the
9790  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9791  * occurs.
9792  */
9793 MonoArray*
9794 mono_reflection_get_custom_attrs (MonoObject *obj)
9795 {
9796         MonoError error;
9797
9798         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9799 }
9800
9801 /*
9802  * mono_reflection_get_custom_attrs_data:
9803  * @obj: a reflection obj handle
9804  *
9805  * Returns an array of System.Reflection.CustomAttributeData,
9806  * which include information about attributes reflected on
9807  * types loaded using the Reflection Only methods
9808  */
9809 MonoArray*
9810 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9811 {
9812         MonoArray *result;
9813         MonoCustomAttrInfo *cinfo;
9814
9815         cinfo = mono_reflection_get_custom_attrs_info (obj);
9816         if (cinfo) {
9817                 result = mono_custom_attrs_data_construct (cinfo);
9818                 if (!cinfo->cached)
9819                         mono_custom_attrs_free (cinfo);
9820         } else
9821                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9822
9823         return result;
9824 }
9825
9826 static MonoReflectionType*
9827 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9828 {
9829         static MonoMethod *method_get_underlying_system_type = NULL;
9830         MonoMethod *usertype_method;
9831
9832         if (!method_get_underlying_system_type)
9833                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9834         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9835         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9836 }
9837
9838
9839 static gboolean
9840 is_corlib_type (MonoClass *klass)
9841 {
9842         return klass->image == mono_defaults.corlib;
9843 }
9844
9845 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9846         static MonoClass *cached_class; \
9847         if (cached_class) \
9848                 return cached_class == _class; \
9849         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9850                 cached_class = _class; \
9851                 return TRUE; \
9852         } \
9853         return FALSE; \
9854 } while (0) \
9855
9856
9857 #ifndef DISABLE_REFLECTION_EMIT
9858 static gboolean
9859 is_sre_array (MonoClass *klass)
9860 {
9861         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9862 }
9863
9864 static gboolean
9865 is_sre_byref (MonoClass *klass)
9866 {
9867         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9868 }
9869
9870 static gboolean
9871 is_sre_pointer (MonoClass *klass)
9872 {
9873         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9874 }
9875
9876 static gboolean
9877 is_sre_generic_instance (MonoClass *klass)
9878 {
9879         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9880 }
9881
9882 static gboolean
9883 is_sre_type_builder (MonoClass *klass)
9884 {
9885         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9886 }
9887
9888 static gboolean
9889 is_sre_method_builder (MonoClass *klass)
9890 {
9891         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9892 }
9893
9894 static gboolean
9895 is_sre_ctor_builder (MonoClass *klass)
9896 {
9897         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9898 }
9899
9900 static gboolean
9901 is_sre_field_builder (MonoClass *klass)
9902 {
9903         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9904 }
9905
9906 static gboolean
9907 is_sre_method_on_tb_inst (MonoClass *klass)
9908 {
9909         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9910 }
9911
9912 static gboolean
9913 is_sre_ctor_on_tb_inst (MonoClass *klass)
9914 {
9915         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9916 }
9917
9918 MonoType*
9919 mono_reflection_type_get_handle (MonoReflectionType* ref)
9920 {
9921         MonoClass *klass;
9922         if (!ref)
9923                 return NULL;
9924         if (ref->type)
9925                 return ref->type;
9926
9927         if (is_usertype (ref)) {
9928                 ref = mono_reflection_type_get_underlying_system_type (ref);
9929                 if (ref == NULL || is_usertype (ref))
9930                         return NULL;
9931                 if (ref->type)
9932                         return ref->type;
9933         }
9934
9935         klass = mono_object_class (ref);
9936
9937         if (is_sre_array (klass)) {
9938                 MonoType *res;
9939                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9940                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9941                 g_assert (base);
9942                 if (sre_array->rank == 0) //single dimentional array
9943                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9944                 else
9945                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9946                 sre_array->type.type = res;
9947                 return res;
9948         } else if (is_sre_byref (klass)) {
9949                 MonoType *res;
9950                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9951                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9952                 g_assert (base);
9953                 res = &mono_class_from_mono_type (base)->this_arg;
9954                 sre_byref->type.type = res;
9955                 return res;
9956         } else if (is_sre_pointer (klass)) {
9957                 MonoType *res;
9958                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9959                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9960                 g_assert (base);
9961                 res = &mono_ptr_class_get (base)->byval_arg;
9962                 sre_pointer->type.type = res;
9963                 return res;
9964         } else if (is_sre_generic_instance (klass)) {
9965                 MonoType *res, **types;
9966                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9967                 int i, count;
9968
9969                 count = mono_array_length (gclass->type_arguments);
9970                 types = g_new0 (MonoType*, count);
9971                 for (i = 0; i < count; ++i) {
9972                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9973                         types [i] = mono_reflection_type_get_handle (t);
9974                         if (!types[i]) {
9975                                 g_free (types);
9976                                 return NULL;
9977                         }
9978                 }
9979
9980                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9981                 g_free (types);
9982                 g_assert (res);
9983                 gclass->type.type = res;
9984                 return res;
9985         }
9986
9987         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9988         return NULL;
9989 }
9990
9991
9992
9993 void
9994 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9995 {
9996         mono_reflection_type_get_handle (type);
9997 }
9998
9999 void
10000 mono_reflection_register_with_runtime (MonoReflectionType *type)
10001 {
10002         MonoType *res = mono_reflection_type_get_handle (type);
10003         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10004         MonoClass *klass;
10005
10006         if (!res)
10007                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10008
10009         klass = mono_class_from_mono_type (res);
10010
10011         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10012         mono_domain_lock (domain);
10013
10014         if (!image_is_dynamic (klass->image)) {
10015                 mono_class_setup_supertypes (klass);
10016         } else {
10017                 if (!domain->type_hash)
10018                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10019                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10020                 mono_g_hash_table_insert (domain->type_hash, res, type);
10021         }
10022         mono_domain_unlock (domain);
10023         mono_loader_unlock ();
10024 }
10025
10026 /**
10027  * LOCKING: Assumes the loader lock is held.
10028  */
10029 static MonoMethodSignature*
10030 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10031         MonoMethodSignature *sig;
10032         int count, i;
10033
10034         count = parameters? mono_array_length (parameters): 0;
10035
10036         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10037         sig->param_count = count;
10038         sig->sentinelpos = -1; /* FIXME */
10039         for (i = 0; i < count; ++i)
10040                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10041         return sig;
10042 }
10043
10044 /**
10045  * LOCKING: Assumes the loader lock is held.
10046  */
10047 static MonoMethodSignature*
10048 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10049         MonoMethodSignature *sig;
10050
10051         sig = parameters_to_signature (image, ctor->parameters);
10052         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10053         sig->ret = &mono_defaults.void_class->byval_arg;
10054         return sig;
10055 }
10056
10057 /**
10058  * LOCKING: Assumes the loader lock is held.
10059  */
10060 static MonoMethodSignature*
10061 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10062         MonoMethodSignature *sig;
10063
10064         sig = parameters_to_signature (image, method->parameters);
10065         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10066         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10067         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10068         return sig;
10069 }
10070
10071 static MonoMethodSignature*
10072 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10073         MonoMethodSignature *sig;
10074
10075         sig = parameters_to_signature (NULL, method->parameters);
10076         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10077         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10078         sig->generic_param_count = 0;
10079         return sig;
10080 }
10081
10082 static void
10083 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10084 {
10085         MonoClass *klass = mono_object_class (prop);
10086         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10087                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10088                 *name = mono_string_to_utf8 (pb->name);
10089                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10090         } else {
10091                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10092                 *name = g_strdup (p->property->name);
10093                 if (p->property->get)
10094                         *type = mono_method_signature (p->property->get)->ret;
10095                 else
10096                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10097         }
10098 }
10099
10100 static void
10101 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10102 {
10103         MonoClass *klass = mono_object_class (field);
10104         if (strcmp (klass->name, "FieldBuilder") == 0) {
10105                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10106                 *name = mono_string_to_utf8 (fb->name);
10107                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10108         } else {
10109                 MonoReflectionField *f = (MonoReflectionField *)field;
10110                 *name = g_strdup (mono_field_get_name (f->field));
10111                 *type = f->field->type;
10112         }
10113 }
10114
10115 #else /* DISABLE_REFLECTION_EMIT */
10116
10117 void
10118 mono_reflection_register_with_runtime (MonoReflectionType *type)
10119 {
10120         /* This is empty */
10121 }
10122
10123 static gboolean
10124 is_sre_type_builder (MonoClass *klass)
10125 {
10126         return FALSE;
10127 }
10128
10129 static gboolean
10130 is_sre_generic_instance (MonoClass *klass)
10131 {
10132         return FALSE;
10133 }
10134
10135 static void
10136 init_type_builder_generics (MonoObject *type)
10137 {
10138 }
10139
10140 #endif /* !DISABLE_REFLECTION_EMIT */
10141
10142
10143 static gboolean
10144 is_sr_mono_field (MonoClass *klass)
10145 {
10146         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10147 }
10148
10149 static gboolean
10150 is_sr_mono_property (MonoClass *klass)
10151 {
10152         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10153 }
10154
10155 static gboolean
10156 is_sr_mono_method (MonoClass *klass)
10157 {
10158         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10159 }
10160
10161 static gboolean
10162 is_sr_mono_cmethod (MonoClass *klass)
10163 {
10164         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10165 }
10166
10167 static gboolean
10168 is_sr_mono_generic_method (MonoClass *klass)
10169 {
10170         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10171 }
10172
10173 static gboolean
10174 is_sr_mono_generic_cmethod (MonoClass *klass)
10175 {
10176         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10177 }
10178
10179 gboolean
10180 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10181 {
10182         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10183 }
10184
10185 static gboolean
10186 is_usertype (MonoReflectionType *ref)
10187 {
10188         MonoClass *klass = mono_object_class (ref);
10189         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10190 }
10191
10192 static MonoReflectionType*
10193 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10194 {
10195         mono_error_init (error);
10196         if (!type || type->type)
10197                 return type;
10198
10199         if (is_usertype (type)) {
10200                 type = mono_reflection_type_get_underlying_system_type (type);
10201                 if (is_usertype (type)) {
10202                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10203                         return NULL;
10204                 }
10205         }
10206
10207         return type;
10208 }
10209 /*
10210  * Encode a value in a custom attribute stream of bytes.
10211  * The value to encode is either supplied as an object in argument val
10212  * (valuetypes are boxed), or as a pointer to the data in the
10213  * argument argval.
10214  * @type represents the type of the value
10215  * @buffer is the start of the buffer
10216  * @p the current position in the buffer
10217  * @buflen contains the size of the buffer and is used to return the new buffer size
10218  * if this needs to be realloced.
10219  * @retbuffer and @retp return the start and the position of the buffer
10220  */
10221 static void
10222 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10223 {
10224         MonoTypeEnum simple_type;
10225         
10226         if ((p-buffer) + 10 >= *buflen) {
10227                 char *newbuf;
10228                 *buflen *= 2;
10229                 newbuf = (char *)g_realloc (buffer, *buflen);
10230                 p = newbuf + (p-buffer);
10231                 buffer = newbuf;
10232         }
10233         if (!argval)
10234                 argval = ((char*)arg + sizeof (MonoObject));
10235         simple_type = type->type;
10236 handle_enum:
10237         switch (simple_type) {
10238         case MONO_TYPE_BOOLEAN:
10239         case MONO_TYPE_U1:
10240         case MONO_TYPE_I1:
10241                 *p++ = *argval;
10242                 break;
10243         case MONO_TYPE_CHAR:
10244         case MONO_TYPE_U2:
10245         case MONO_TYPE_I2:
10246                 swap_with_size (p, argval, 2, 1);
10247                 p += 2;
10248                 break;
10249         case MONO_TYPE_U4:
10250         case MONO_TYPE_I4:
10251         case MONO_TYPE_R4:
10252                 swap_with_size (p, argval, 4, 1);
10253                 p += 4;
10254                 break;
10255         case MONO_TYPE_R8:
10256                 swap_with_size (p, argval, 8, 1);
10257                 p += 8;
10258                 break;
10259         case MONO_TYPE_U8:
10260         case MONO_TYPE_I8:
10261                 swap_with_size (p, argval, 8, 1);
10262                 p += 8;
10263                 break;
10264         case MONO_TYPE_VALUETYPE:
10265                 if (type->data.klass->enumtype) {
10266                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10267                         goto handle_enum;
10268                 } else {
10269                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10270                 }
10271                 break;
10272         case MONO_TYPE_STRING: {
10273                 char *str;
10274                 guint32 slen;
10275                 if (!arg) {
10276                         *p++ = 0xFF;
10277                         break;
10278                 }
10279                 str = mono_string_to_utf8 ((MonoString*)arg);
10280                 slen = strlen (str);
10281                 if ((p-buffer) + 10 + slen >= *buflen) {
10282                         char *newbuf;
10283                         *buflen *= 2;
10284                         *buflen += slen;
10285                         newbuf = (char *)g_realloc (buffer, *buflen);
10286                         p = newbuf + (p-buffer);
10287                         buffer = newbuf;
10288                 }
10289                 mono_metadata_encode_value (slen, p, &p);
10290                 memcpy (p, str, slen);
10291                 p += slen;
10292                 g_free (str);
10293                 break;
10294         }
10295         case MONO_TYPE_CLASS: {
10296                 char *str;
10297                 guint32 slen;
10298                 if (!arg) {
10299                         *p++ = 0xFF;
10300                         break;
10301                 }
10302 handle_type:
10303                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10304                 slen = strlen (str);
10305                 if ((p-buffer) + 10 + slen >= *buflen) {
10306                         char *newbuf;
10307                         *buflen *= 2;
10308                         *buflen += slen;
10309                         newbuf = (char *)g_realloc (buffer, *buflen);
10310                         p = newbuf + (p-buffer);
10311                         buffer = newbuf;
10312                 }
10313                 mono_metadata_encode_value (slen, p, &p);
10314                 memcpy (p, str, slen);
10315                 p += slen;
10316                 g_free (str);
10317                 break;
10318         }
10319         case MONO_TYPE_SZARRAY: {
10320                 int len, i;
10321                 MonoClass *eclass, *arg_eclass;
10322
10323                 if (!arg) {
10324                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10325                         break;
10326                 }
10327                 len = mono_array_length ((MonoArray*)arg);
10328                 *p++ = len & 0xff;
10329                 *p++ = (len >> 8) & 0xff;
10330                 *p++ = (len >> 16) & 0xff;
10331                 *p++ = (len >> 24) & 0xff;
10332                 *retp = p;
10333                 *retbuffer = buffer;
10334                 eclass = type->data.klass;
10335                 arg_eclass = mono_object_class (arg)->element_class;
10336
10337                 if (!eclass) {
10338                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10339                         eclass = mono_defaults.object_class;
10340                 }
10341                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10342                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10343                         int elsize = mono_class_array_element_size (arg_eclass);
10344                         for (i = 0; i < len; ++i) {
10345                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10346                                 elptr += elsize;
10347                         }
10348                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10349                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10350                         int elsize = mono_class_array_element_size (eclass);
10351                         for (i = 0; i < len; ++i) {
10352                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10353                                 elptr += elsize;
10354                         }
10355                 } else {
10356                         for (i = 0; i < len; ++i) {
10357                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10358                         }
10359                 }
10360                 break;
10361         }
10362         case MONO_TYPE_OBJECT: {
10363                 MonoClass *klass;
10364                 char *str;
10365                 guint32 slen;
10366
10367                 /*
10368                  * The parameter type is 'object' but the type of the actual
10369                  * argument is not. So we have to add type information to the blob
10370                  * too. This is completely undocumented in the spec.
10371                  */
10372
10373                 if (arg == NULL) {
10374                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10375                         *p++ = 0xFF;
10376                         break;
10377                 }
10378                 
10379                 klass = mono_object_class (arg);
10380
10381                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10382                         *p++ = 0x50;
10383                         goto handle_type;
10384                 } else if (klass->enumtype) {
10385                         *p++ = 0x55;
10386                 } else if (klass == mono_defaults.string_class) {
10387                         simple_type = MONO_TYPE_STRING;
10388                         *p++ = 0x0E;
10389                         goto handle_enum;
10390                 } else if (klass->rank == 1) {
10391                         *p++ = 0x1D;
10392                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10393                                 /* See Partition II, Appendix B3 */
10394                                 *p++ = 0x51;
10395                         else
10396                                 *p++ = klass->element_class->byval_arg.type;
10397                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10398                         break;
10399                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10400                         *p++ = simple_type = klass->byval_arg.type;
10401                         goto handle_enum;
10402                 } else {
10403                         g_error ("unhandled type in custom attr");
10404                 }
10405                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10406                 slen = strlen (str);
10407                 if ((p-buffer) + 10 + slen >= *buflen) {
10408                         char *newbuf;
10409                         *buflen *= 2;
10410                         *buflen += slen;
10411                         newbuf = (char *)g_realloc (buffer, *buflen);
10412                         p = newbuf + (p-buffer);
10413                         buffer = newbuf;
10414                 }
10415                 mono_metadata_encode_value (slen, p, &p);
10416                 memcpy (p, str, slen);
10417                 p += slen;
10418                 g_free (str);
10419                 simple_type = mono_class_enum_basetype (klass)->type;
10420                 goto handle_enum;
10421         }
10422         default:
10423                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10424         }
10425         *retp = p;
10426         *retbuffer = buffer;
10427 }
10428
10429 static void
10430 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10431 {
10432         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10433                 char *str = type_get_qualified_name (type, NULL);
10434                 int slen = strlen (str);
10435
10436                 *p++ = 0x55;
10437                 /*
10438                  * This seems to be optional...
10439                  * *p++ = 0x80;
10440                  */
10441                 mono_metadata_encode_value (slen, p, &p);
10442                 memcpy (p, str, slen);
10443                 p += slen;
10444                 g_free (str);
10445         } else if (type->type == MONO_TYPE_OBJECT) {
10446                 *p++ = 0x51;
10447         } else if (type->type == MONO_TYPE_CLASS) {
10448                 /* it should be a type: encode_cattr_value () has the check */
10449                 *p++ = 0x50;
10450         } else {
10451                 mono_metadata_encode_value (type->type, p, &p);
10452                 if (type->type == MONO_TYPE_SZARRAY)
10453                         /* See the examples in Partition VI, Annex B */
10454                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10455         }
10456
10457         *retp = p;
10458 }
10459
10460 #ifndef DISABLE_REFLECTION_EMIT
10461 static void
10462 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10463 {
10464         int len;
10465         /* Preallocate a large enough buffer */
10466         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10467                 char *str = type_get_qualified_name (type, NULL);
10468                 len = strlen (str);
10469                 g_free (str);
10470         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10471                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10472                 len = strlen (str);
10473                 g_free (str);
10474         } else {
10475                 len = 0;
10476         }
10477         len += strlen (name);
10478
10479         if ((p-buffer) + 20 + len >= *buflen) {
10480                 char *newbuf;
10481                 *buflen *= 2;
10482                 *buflen += len;
10483                 newbuf = (char *)g_realloc (buffer, *buflen);
10484                 p = newbuf + (p-buffer);
10485                 buffer = newbuf;
10486         }
10487
10488         encode_field_or_prop_type (type, p, &p);
10489
10490         len = strlen (name);
10491         mono_metadata_encode_value (len, p, &p);
10492         memcpy (p, name, len);
10493         p += len;
10494         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10495         *retp = p;
10496         *retbuffer = buffer;
10497 }
10498
10499 /*
10500  * mono_reflection_get_custom_attrs_blob:
10501  * @ctor: custom attribute constructor
10502  * @ctorArgs: arguments o the constructor
10503  * @properties:
10504  * @propValues:
10505  * @fields:
10506  * @fieldValues:
10507  * 
10508  * Creates the blob of data that needs to be saved in the metadata and that represents
10509  * the custom attributed described by @ctor, @ctorArgs etc.
10510  * Returns: a Byte array representing the blob of data.
10511  */
10512 MonoArray*
10513 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10514 {
10515         MonoArray *result;
10516         MonoMethodSignature *sig;
10517         MonoObject *arg;
10518         char *buffer, *p;
10519         guint32 buflen, i;
10520
10521         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10522                 /* sig is freed later so allocate it in the heap */
10523                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10524         } else {
10525                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10526         }
10527
10528         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10529         buflen = 256;
10530         p = buffer = (char *)g_malloc (buflen);
10531         /* write the prolog */
10532         *p++ = 1;
10533         *p++ = 0;
10534         for (i = 0; i < sig->param_count; ++i) {
10535                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10536                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10537         }
10538         i = 0;
10539         if (properties)
10540                 i += mono_array_length (properties);
10541         if (fields)
10542                 i += mono_array_length (fields);
10543         *p++ = i & 0xff;
10544         *p++ = (i >> 8) & 0xff;
10545         if (properties) {
10546                 MonoObject *prop;
10547                 for (i = 0; i < mono_array_length (properties); ++i) {
10548                         MonoType *ptype;
10549                         char *pname;
10550
10551                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10552                         get_prop_name_and_type (prop, &pname, &ptype);
10553                         *p++ = 0x54; /* PROPERTY signature */
10554                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10555                         g_free (pname);
10556                 }
10557         }
10558
10559         if (fields) {
10560                 MonoObject *field;
10561                 for (i = 0; i < mono_array_length (fields); ++i) {
10562                         MonoType *ftype;
10563                         char *fname;
10564
10565                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10566                         get_field_name_and_type (field, &fname, &ftype);
10567                         *p++ = 0x53; /* FIELD signature */
10568                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10569                         g_free (fname);
10570                 }
10571         }
10572
10573         g_assert (p - buffer <= buflen);
10574         buflen = p - buffer;
10575         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10576         p = mono_array_addr (result, char, 0);
10577         memcpy (p, buffer, buflen);
10578         g_free (buffer);
10579         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10580                 g_free (sig);
10581         return result;
10582 }
10583
10584 /*
10585  * mono_reflection_setup_internal_class:
10586  * @tb: a TypeBuilder object
10587  *
10588  * Creates a MonoClass that represents the TypeBuilder.
10589  * This is a trick that lets us simplify a lot of reflection code
10590  * (and will allow us to support Build and Run assemblies easier).
10591  */
10592 void
10593 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10594 {
10595         MonoError error;
10596         MonoClass *klass, *parent;
10597
10598         RESOLVE_TYPE (tb->parent, &error);
10599         mono_error_raise_exception (&error); /* FIXME don't raise here */
10600
10601         mono_loader_lock ();
10602
10603         if (tb->parent) {
10604                 /* check so we can compile corlib correctly */
10605                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10606                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10607                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10608                 } else {
10609                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10610                 }
10611         } else {
10612                 parent = NULL;
10613         }
10614         
10615         /* the type has already being created: it means we just have to change the parent */
10616         if (tb->type.type) {
10617                 klass = mono_class_from_mono_type (tb->type.type);
10618                 klass->parent = NULL;
10619                 /* fool mono_class_setup_parent */
10620                 klass->supertypes = NULL;
10621                 mono_class_setup_parent (klass, parent);
10622                 mono_class_setup_mono_type (klass);
10623                 mono_loader_unlock ();
10624                 return;
10625         }
10626
10627         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10628
10629         klass->image = &tb->module->dynamic_image->image;
10630
10631         klass->inited = 1; /* we lie to the runtime */
10632         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10633         if (!mono_error_ok (&error))
10634                 goto failure;
10635         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10636         if (!mono_error_ok (&error))
10637                 goto failure;
10638         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10639         klass->flags = tb->attrs;
10640         
10641         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10642
10643         klass->element_class = klass;
10644
10645         if (mono_class_get_ref_info (klass) == NULL) {
10646
10647                 mono_class_set_ref_info (klass, tb);
10648
10649                 /* Put into cache so mono_class_get_checked () will find it.
10650                 Skip nested types as those should not be available on the global scope. */
10651                 if (!tb->nesting_type)
10652                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10653
10654                 /*
10655                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10656                 by performing a mono_class_get which does the full resolution.
10657
10658                 Working around this semantics would require us to write a lot of code for no clear advantage.
10659                 */
10660                 mono_image_append_class_to_reflection_info_set (klass);
10661         } else {
10662                 g_assert (mono_class_get_ref_info (klass) == tb);
10663         }
10664
10665         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10666
10667         if (parent != NULL) {
10668                 mono_class_setup_parent (klass, parent);
10669         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10670                 const char *old_n = klass->name;
10671                 /* trick to get relative numbering right when compiling corlib */
10672                 klass->name = "BuildingObject";
10673                 mono_class_setup_parent (klass, mono_defaults.object_class);
10674                 klass->name = old_n;
10675         }
10676
10677         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10678                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10679                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10680                 klass->instance_size = sizeof (MonoObject);
10681                 klass->size_inited = 1;
10682                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10683         }
10684
10685         mono_class_setup_mono_type (klass);
10686
10687         mono_class_setup_supertypes (klass);
10688
10689         /*
10690          * FIXME: handle interfaces.
10691          */
10692
10693         tb->type.type = &klass->byval_arg;
10694
10695         if (tb->nesting_type) {
10696                 g_assert (tb->nesting_type->type);
10697                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10698         }
10699
10700         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10701
10702         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10703         
10704         mono_loader_unlock ();
10705         return;
10706
10707 failure:
10708         mono_loader_unlock ();
10709         mono_error_raise_exception (&error);
10710 }
10711
10712 /*
10713  * mono_reflection_setup_generic_class:
10714  * @tb: a TypeBuilder object
10715  *
10716  * Setup the generic class before adding the first generic parameter.
10717  */
10718 void
10719 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10720 {
10721 }
10722
10723 /*
10724  * mono_reflection_create_generic_class:
10725  * @tb: a TypeBuilder object
10726  *
10727  * Creates the generic class after all generic parameters have been added.
10728  */
10729 void
10730 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10731 {
10732         MonoClass *klass;
10733         int count, i;
10734
10735         klass = mono_class_from_mono_type (tb->type.type);
10736
10737         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10738
10739         if (klass->generic_container || (count == 0))
10740                 return;
10741
10742         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10743
10744         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10745
10746         klass->generic_container->owner.klass = klass;
10747         klass->generic_container->type_argc = count;
10748         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10749
10750         klass->is_generic = 1;
10751
10752         for (i = 0; i < count; i++) {
10753                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10754                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10755                 klass->generic_container->type_params [i] = *param;
10756                 /*Make sure we are a diferent type instance */
10757                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10758                 klass->generic_container->type_params [i].info.pklass = NULL;
10759                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10760
10761                 g_assert (klass->generic_container->type_params [i].param.owner);
10762         }
10763
10764         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10765 }
10766
10767 /*
10768  * mono_reflection_create_internal_class:
10769  * @tb: a TypeBuilder object
10770  *
10771  * Actually create the MonoClass that is associated with the TypeBuilder.
10772  */
10773 void
10774 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10775 {
10776         MonoClass *klass;
10777
10778         klass = mono_class_from_mono_type (tb->type.type);
10779
10780         mono_loader_lock ();
10781         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10782                 MonoReflectionFieldBuilder *fb;
10783                 MonoClass *ec;
10784                 MonoType *enum_basetype;
10785
10786                 g_assert (tb->fields != NULL);
10787                 g_assert (mono_array_length (tb->fields) >= 1);
10788
10789                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10790
10791                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10792                         mono_loader_unlock ();
10793                         return;
10794                 }
10795
10796                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10797                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10798                 if (!klass->element_class)
10799                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10800
10801                 /*
10802                  * get the element_class from the current corlib.
10803                  */
10804                 ec = default_class_from_mono_type (enum_basetype);
10805                 klass->instance_size = ec->instance_size;
10806                 klass->size_inited = 1;
10807                 /* 
10808                  * this is almost safe to do with enums and it's needed to be able
10809                  * to create objects of the enum type (for use in SetConstant).
10810                  */
10811                 /* FIXME: Does this mean enums can't have method overrides ? */
10812                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10813         }
10814         mono_loader_unlock ();
10815 }
10816
10817 static MonoMarshalSpec*
10818 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10819                                                                 MonoReflectionMarshal *minfo)
10820 {
10821         MonoMarshalSpec *res;
10822
10823         res = image_g_new0 (image, MonoMarshalSpec, 1);
10824         res->native = (MonoMarshalNative)minfo->type;
10825
10826         switch (minfo->type) {
10827         case MONO_NATIVE_LPARRAY:
10828                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10829                 if (minfo->has_size) {
10830                         res->data.array_data.param_num = minfo->param_num;
10831                         res->data.array_data.num_elem = minfo->count;
10832                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10833                 }
10834                 else {
10835                         res->data.array_data.param_num = -1;
10836                         res->data.array_data.num_elem = -1;
10837                         res->data.array_data.elem_mult = -1;
10838                 }
10839                 break;
10840
10841         case MONO_NATIVE_BYVALTSTR:
10842         case MONO_NATIVE_BYVALARRAY:
10843                 res->data.array_data.num_elem = minfo->count;
10844                 break;
10845
10846         case MONO_NATIVE_CUSTOM:
10847                 if (minfo->marshaltyperef)
10848                         res->data.custom_data.custom_name =
10849                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10850                 if (minfo->mcookie)
10851                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10852                 break;
10853
10854         default:
10855                 break;
10856         }
10857
10858         return res;
10859 }
10860 #endif /* !DISABLE_REFLECTION_EMIT */
10861
10862 MonoReflectionMarshalAsAttribute*
10863 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10864                                                                                    MonoMarshalSpec *spec)
10865 {
10866         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10867         MonoError error;
10868         MonoReflectionType *rt;
10869         MonoReflectionMarshalAsAttribute *minfo;
10870         MonoType *mtype;
10871
10872         if (!System_Reflection_Emit_MarshalAsAttribute) {
10873                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10874                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10875                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10876         }
10877
10878         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10879         mono_error_raise_exception (&error); /* FIXME don't raise here */
10880         minfo->utype = spec->native;
10881
10882         switch (minfo->utype) {
10883         case MONO_NATIVE_LPARRAY:
10884                 minfo->array_subtype = spec->data.array_data.elem_type;
10885                 minfo->size_const = spec->data.array_data.num_elem;
10886                 if (spec->data.array_data.param_num != -1)
10887                         minfo->size_param_index = spec->data.array_data.param_num;
10888                 break;
10889
10890         case MONO_NATIVE_BYVALTSTR:
10891         case MONO_NATIVE_BYVALARRAY:
10892                 minfo->size_const = spec->data.array_data.num_elem;
10893                 break;
10894
10895         case MONO_NATIVE_CUSTOM:
10896                 if (spec->data.custom_data.custom_name) {
10897                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10898                         if (mtype) {
10899                                 rt = mono_type_get_object_checked (domain, mtype, &error);
10900                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10901
10902                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10903                         }
10904
10905                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10906                 }
10907                 if (spec->data.custom_data.cookie)
10908                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10909                 break;
10910
10911         default:
10912                 break;
10913         }
10914
10915         return minfo;
10916 }
10917
10918 #ifndef DISABLE_REFLECTION_EMIT
10919 static MonoMethod*
10920 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10921                                          ReflectionMethodBuilder *rmb,
10922                                          MonoMethodSignature *sig)
10923 {
10924         MonoError error;
10925         MonoMethod *m;
10926         MonoMethodWrapper *wrapperm;
10927         MonoMarshalSpec **specs;
10928         MonoReflectionMethodAux *method_aux;
10929         MonoImage *image;
10930         gboolean dynamic;
10931         int i;
10932
10933         mono_error_init (&error);
10934         /*
10935          * Methods created using a MethodBuilder should have their memory allocated
10936          * inside the image mempool, while dynamic methods should have their memory
10937          * malloc'd.
10938          */
10939         dynamic = rmb->refs != NULL;
10940         image = dynamic ? NULL : klass->image;
10941
10942         if (!dynamic)
10943                 g_assert (!klass->generic_class);
10944
10945         mono_loader_lock ();
10946
10947         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10948                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10949                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10950         else
10951                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10952
10953         wrapperm = (MonoMethodWrapper*)m;
10954
10955         m->dynamic = dynamic;
10956         m->slot = -1;
10957         m->flags = rmb->attrs;
10958         m->iflags = rmb->iattrs;
10959         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10960         m->klass = klass;
10961         m->signature = sig;
10962         m->sre_method = TRUE;
10963         m->skip_visibility = rmb->skip_visibility;
10964         if (rmb->table_idx)
10965                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10966
10967         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10968                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10969                         m->string_ctor = 1;
10970
10971                 m->signature->pinvoke = 1;
10972         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10973                 m->signature->pinvoke = 1;
10974
10975                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10976
10977                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10978                 g_assert (mono_error_ok (&error));
10979                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10980                 g_assert (mono_error_ok (&error));
10981                 
10982                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10983
10984                 if (image_is_dynamic (klass->image))
10985                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10986
10987                 mono_loader_unlock ();
10988
10989                 return m;
10990         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10991                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10992                 MonoMethodHeader *header;
10993                 guint32 code_size;
10994                 gint32 max_stack, i;
10995                 gint32 num_locals = 0;
10996                 gint32 num_clauses = 0;
10997                 guint8 *code;
10998
10999                 if (rmb->ilgen) {
11000                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11001                         code_size = rmb->ilgen->code_len;
11002                         max_stack = rmb->ilgen->max_stack;
11003                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11004                         if (rmb->ilgen->ex_handlers)
11005                                 num_clauses = method_count_clauses (rmb->ilgen);
11006                 } else {
11007                         if (rmb->code) {
11008                                 code = mono_array_addr (rmb->code, guint8, 0);
11009                                 code_size = mono_array_length (rmb->code);
11010                                 /* we probably need to run a verifier on the code... */
11011                                 max_stack = 8; 
11012                         }
11013                         else {
11014                                 code = NULL;
11015                                 code_size = 0;
11016                                 max_stack = 8;
11017                         }
11018                 }
11019
11020                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11021                 header->code_size = code_size;
11022                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11023                 memcpy ((char*)header->code, code, code_size);
11024                 header->max_stack = max_stack;
11025                 header->init_locals = rmb->init_locals;
11026                 header->num_locals = num_locals;
11027
11028                 for (i = 0; i < num_locals; ++i) {
11029                         MonoReflectionLocalBuilder *lb = 
11030                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11031
11032                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11033                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11034                 }
11035
11036                 header->num_clauses = num_clauses;
11037                 if (num_clauses) {
11038                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11039                                  rmb->ilgen, num_clauses);
11040                 }
11041
11042                 wrapperm->header = header;
11043         }
11044
11045         if (rmb->generic_params) {
11046                 int count = mono_array_length (rmb->generic_params);
11047                 MonoGenericContainer *container = rmb->generic_container;
11048
11049                 g_assert (container);
11050
11051                 container->type_argc = count;
11052                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11053                 container->owner.method = m;
11054                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11055
11056                 m->is_generic = TRUE;
11057                 mono_method_set_generic_container (m, container);
11058
11059                 for (i = 0; i < count; i++) {
11060                         MonoReflectionGenericParam *gp =
11061                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11062                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11063                         container->type_params [i] = *param;
11064                 }
11065
11066                 /*
11067                  * The method signature might have pointers to generic parameters that belong to other methods.
11068                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11069                  * generic parameters.
11070                  */
11071                 for (i = 0; i < m->signature->param_count; ++i) {
11072                         MonoType *t = m->signature->params [i];
11073                         if (t->type == MONO_TYPE_MVAR) {
11074                                 MonoGenericParam *gparam =  t->data.generic_param;
11075                                 if (gparam->num < count) {
11076                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11077                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11078                                 }
11079
11080                         }
11081                 }
11082
11083                 if (klass->generic_container) {
11084                         container->parent = klass->generic_container;
11085                         container->context.class_inst = klass->generic_container->context.class_inst;
11086                 }
11087                 container->context.method_inst = mono_get_shared_generic_inst (container);
11088         }
11089
11090         if (rmb->refs) {
11091                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11092                 int i;
11093                 void **data;
11094
11095                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11096
11097                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11098                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11099                 for (i = 0; i < rmb->nrefs; ++i)
11100                         data [i + 1] = rmb->refs [i];
11101         }
11102
11103         method_aux = NULL;
11104
11105         /* Parameter info */
11106         if (rmb->pinfo) {
11107                 if (!method_aux)
11108                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11109                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11110                 for (i = 0; i <= m->signature->param_count; ++i) {
11111                         MonoReflectionParamBuilder *pb;
11112                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11113                                 if ((i > 0) && (pb->attrs)) {
11114                                         /* Make a copy since it might point to a shared type structure */
11115                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11116                                         m->signature->params [i - 1]->attrs = pb->attrs;
11117                                 }
11118
11119                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11120                                         MonoDynamicImage *assembly;
11121                                         guint32 idx, len;
11122                                         MonoTypeEnum def_type;
11123                                         char *p;
11124                                         const char *p2;
11125
11126                                         if (!method_aux->param_defaults) {
11127                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11128                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11129                                         }
11130                                         assembly = (MonoDynamicImage*)klass->image;
11131                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11132                                         /* Copy the data from the blob since it might get realloc-ed */
11133                                         p = assembly->blob.data + idx;
11134                                         len = mono_metadata_decode_blob_size (p, &p2);
11135                                         len += p2 - p;
11136                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11137                                         method_aux->param_default_types [i] = def_type;
11138                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11139                                 }
11140
11141                                 if (pb->name) {
11142                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11143                                         g_assert (mono_error_ok (&error));
11144                                 }
11145                                 if (pb->cattrs) {
11146                                         if (!method_aux->param_cattr)
11147                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11148                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11149                                 }
11150                         }
11151                 }
11152         }
11153
11154         /* Parameter marshalling */
11155         specs = NULL;
11156         if (rmb->pinfo)         
11157                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11158                         MonoReflectionParamBuilder *pb;
11159                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11160                                 if (pb->marshal_info) {
11161                                         if (specs == NULL)
11162                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11163                                         specs [pb->position] = 
11164                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11165                                 }
11166                         }
11167                 }
11168         if (specs != NULL) {
11169                 if (!method_aux)
11170                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11171                 method_aux->param_marshall = specs;
11172         }
11173
11174         if (image_is_dynamic (klass->image) && method_aux)
11175                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11176
11177         mono_loader_unlock ();
11178
11179         return m;
11180 }       
11181
11182 static MonoMethod*
11183 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11184 {
11185         ReflectionMethodBuilder rmb;
11186         MonoMethodSignature *sig;
11187
11188         mono_loader_lock ();
11189         sig = ctor_builder_to_signature (klass->image, mb);
11190         mono_loader_unlock ();
11191
11192         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11193
11194         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11195         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11196
11197         /* If we are in a generic class, we might be called multiple times from inflate_method */
11198         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11199                 /* ilgen is no longer needed */
11200                 mb->ilgen = NULL;
11201         }
11202
11203         return mb->mhandle;
11204 }
11205
11206 static MonoMethod*
11207 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11208 {
11209         ReflectionMethodBuilder rmb;
11210         MonoMethodSignature *sig;
11211
11212         mono_loader_lock ();
11213         sig = method_builder_to_signature (klass->image, mb);
11214         mono_loader_unlock ();
11215
11216         reflection_methodbuilder_from_method_builder (&rmb, mb);
11217
11218         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11219         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11220
11221         /* If we are in a generic class, we might be called multiple times from inflate_method */
11222         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11223                 /* ilgen is no longer needed */
11224                 mb->ilgen = NULL;
11225         }
11226         return mb->mhandle;
11227 }
11228
11229 static MonoClassField*
11230 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11231 {
11232         MonoClassField *field;
11233         MonoType *custom;
11234         MonoError error;
11235
11236         field = g_new0 (MonoClassField, 1);
11237
11238         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11239         g_assert (mono_error_ok (&error));
11240         if (fb->attrs || fb->modreq || fb->modopt) {
11241                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11242                 field->type->attrs = fb->attrs;
11243
11244                 g_assert (image_is_dynamic (klass->image));
11245                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11246                 g_free (field->type);
11247                 field->type = mono_metadata_type_dup (klass->image, custom);
11248                 g_free (custom);
11249         } else {
11250                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11251         }
11252         if (fb->offset != -1)
11253                 field->offset = fb->offset;
11254         field->parent = klass;
11255         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11256
11257         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11258
11259         return field;
11260 }
11261 #endif
11262
11263 MonoType*
11264 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11265 {
11266         MonoClass *klass;
11267         MonoReflectionTypeBuilder *tb = NULL;
11268         gboolean is_dynamic = FALSE;
11269         MonoClass *geninst;
11270
11271         mono_loader_lock ();
11272
11273         if (is_sre_type_builder (mono_object_class (type))) {
11274                 tb = (MonoReflectionTypeBuilder *) type;
11275
11276                 is_dynamic = TRUE;
11277         } else if (is_sre_generic_instance (mono_object_class (type))) {
11278                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11279                 MonoReflectionType *gtd = rgi->generic_type;
11280
11281                 if (is_sre_type_builder (mono_object_class (gtd))) {
11282                         tb = (MonoReflectionTypeBuilder *)gtd;
11283                         is_dynamic = TRUE;
11284                 }
11285         }
11286
11287         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11288         if (tb && tb->generic_container)
11289                 mono_reflection_create_generic_class (tb);
11290
11291         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11292         if (!klass->generic_container) {
11293                 mono_loader_unlock ();
11294                 return NULL;
11295         }
11296
11297         if (klass->wastypebuilder) {
11298                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11299
11300                 is_dynamic = TRUE;
11301         }
11302
11303         mono_loader_unlock ();
11304
11305         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11306
11307         return &geninst->byval_arg;
11308 }
11309
11310 MonoClass*
11311 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11312 {
11313         MonoGenericClass *gclass;
11314         MonoGenericInst *inst;
11315
11316         g_assert (klass->generic_container);
11317
11318         inst = mono_metadata_get_generic_inst (type_argc, types);
11319         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11320
11321         return mono_generic_class_get_class (gclass);
11322 }
11323
11324 MonoReflectionMethod*
11325 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11326 {
11327         MonoError error;
11328         MonoClass *klass;
11329         MonoMethod *method, *inflated;
11330         MonoMethodInflated *imethod;
11331         MonoGenericContext tmp_context;
11332         MonoGenericInst *ginst;
11333         MonoType **type_argv;
11334         int count, i;
11335
11336         /*FIXME but this no longer should happen*/
11337         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11338 #ifndef DISABLE_REFLECTION_EMIT
11339                 MonoReflectionMethodBuilder *mb = NULL;
11340                 MonoReflectionTypeBuilder *tb;
11341                 MonoClass *klass;
11342
11343                 mb = (MonoReflectionMethodBuilder *) rmethod;
11344                 tb = (MonoReflectionTypeBuilder *) mb->type;
11345                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11346
11347                 method = methodbuilder_to_mono_method (klass, mb);
11348 #else
11349                 g_assert_not_reached ();
11350                 method = NULL;
11351 #endif
11352         } else {
11353                 method = rmethod->method;
11354         }
11355
11356         klass = method->klass;
11357
11358         if (method->is_inflated)
11359                 method = ((MonoMethodInflated *) method)->declaring;
11360
11361         count = mono_method_signature (method)->generic_param_count;
11362         if (count != mono_array_length (types))
11363                 return NULL;
11364
11365         type_argv = g_new0 (MonoType *, count);
11366         for (i = 0; i < count; i++) {
11367                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11368                 type_argv [i] = mono_reflection_type_get_handle (garg);
11369         }
11370         ginst = mono_metadata_get_generic_inst (count, type_argv);
11371         g_free (type_argv);
11372
11373         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11374         tmp_context.method_inst = ginst;
11375
11376         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11377         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11378         imethod = (MonoMethodInflated *) inflated;
11379
11380         /*FIXME but I think this is no longer necessary*/
11381         if (image_is_dynamic (method->klass->image)) {
11382                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11383                 /*
11384                  * This table maps metadata structures representing inflated methods/fields
11385                  * to the reflection objects representing their generic definitions.
11386                  */
11387                 mono_image_lock ((MonoImage*)image);
11388                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11389                 mono_image_unlock ((MonoImage*)image);
11390         }
11391
11392         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11393                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11394         
11395         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11396         mono_error_raise_exception (&error); /* FIXME don't raise here */
11397         return ret;
11398 }
11399
11400 #ifndef DISABLE_REFLECTION_EMIT
11401
11402 static MonoMethod *
11403 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11404 {
11405         MonoMethodInflated *imethod;
11406         MonoGenericContext *context;
11407         int i;
11408
11409         /*
11410          * With generic code sharing the klass might not be inflated.
11411          * This can happen because classes inflated with their own
11412          * type arguments are "normalized" to the uninflated class.
11413          */
11414         if (!klass->generic_class)
11415                 return method;
11416
11417         context = mono_class_get_context (klass);
11418
11419         if (klass->method.count && klass->methods) {
11420                 /* Find the already created inflated method */
11421                 for (i = 0; i < klass->method.count; ++i) {
11422                         g_assert (klass->methods [i]->is_inflated);
11423                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11424                                 break;
11425                 }
11426                 g_assert (i < klass->method.count);
11427                 imethod = (MonoMethodInflated*)klass->methods [i];
11428         } else {
11429                 MonoError error;
11430                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11431                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11432         }
11433
11434         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11435                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11436
11437                 mono_image_lock ((MonoImage*)image);
11438                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11439                 mono_image_unlock ((MonoImage*)image);
11440         }
11441         return (MonoMethod *) imethod;
11442 }
11443
11444 static MonoMethod *
11445 inflate_method (MonoReflectionType *type, MonoObject *obj)
11446 {
11447         MonoMethod *method;
11448         MonoClass *gklass;
11449
11450         MonoClass *type_class = mono_object_class (type);
11451
11452         if (is_sre_generic_instance (type_class)) {
11453                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11454                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11455         } else if (is_sre_type_builder (type_class)) {
11456                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11457         } else if (type->type) {
11458                 gklass = mono_class_from_mono_type (type->type);
11459                 gklass = mono_class_get_generic_type_definition (gklass);
11460         } else {
11461                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11462         }
11463
11464         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11465                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11466                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11467                 else
11468                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11469         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11470                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11471         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11472                 method = ((MonoReflectionMethod *) obj)->method;
11473         else {
11474                 method = NULL; /* prevent compiler warning */
11475                 g_error ("can't handle type %s", obj->vtable->klass->name);
11476         }
11477
11478         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11479 }
11480
11481 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11482 void
11483 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11484 {
11485         MonoGenericClass *gclass;
11486         MonoDynamicGenericClass *dgclass;
11487         MonoClass *klass, *gklass;
11488         MonoType *gtype;
11489         int i;
11490
11491         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11492         klass = mono_class_from_mono_type (gtype);
11493         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11494         gclass = gtype->data.generic_class;
11495
11496         if (!gclass->is_dynamic)
11497                 return;
11498
11499         dgclass = (MonoDynamicGenericClass *) gclass;
11500
11501         if (dgclass->initialized)
11502                 return;
11503
11504         gklass = gclass->container_class;
11505         mono_class_init (gklass);
11506
11507         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11508
11509         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11510         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11511         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11512
11513         for (i = 0; i < dgclass->count_fields; i++) {
11514                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11515                 MonoClassField *field, *inflated_field = NULL;
11516
11517                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11518                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11519                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11520                         field = ((MonoReflectionField *) obj)->field;
11521                 else {
11522                         field = NULL; /* prevent compiler warning */
11523                         g_assert_not_reached ();
11524                 }
11525
11526                 dgclass->fields [i] = *field;
11527                 dgclass->fields [i].parent = klass;
11528                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11529                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11530                 dgclass->field_generic_types [i] = field->type;
11531                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11532                 dgclass->field_objects [i] = obj;
11533
11534                 if (inflated_field) {
11535                         g_free (inflated_field);
11536                 } else {
11537                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11538                 }
11539         }
11540
11541         dgclass->initialized = TRUE;
11542 }
11543
11544 void
11545 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11546 {
11547         MonoDynamicGenericClass *dgclass;
11548         int i;
11549
11550         g_assert (gclass->is_dynamic);
11551
11552         dgclass = (MonoDynamicGenericClass *)gclass;
11553
11554         for (i = 0; i < dgclass->count_fields; ++i) {
11555                 MonoClassField *field = dgclass->fields + i;
11556                 mono_metadata_free_type (field->type);
11557                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11558         }
11559 }
11560
11561 static void
11562 fix_partial_generic_class (MonoClass *klass)
11563 {
11564         MonoClass *gklass = klass->generic_class->container_class;
11565         MonoDynamicGenericClass *dgclass;
11566         int i;
11567
11568         if (klass->wastypebuilder)
11569                 return;
11570
11571         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11572         if (klass->parent != gklass->parent) {
11573                 MonoError error;
11574                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11575                 if (mono_error_ok (&error)) {
11576                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11577                         mono_metadata_free_type (parent_type);
11578                         if (parent != klass->parent) {
11579                                 /*fool mono_class_setup_parent*/
11580                                 klass->supertypes = NULL;
11581                                 mono_class_setup_parent (klass, parent);
11582                         }
11583                 } else {
11584                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11585                         mono_error_cleanup (&error);
11586                         if (gklass->wastypebuilder)
11587                                 klass->wastypebuilder = TRUE;
11588                         return;
11589                 }
11590         }
11591
11592         if (!dgclass->initialized)
11593                 return;
11594
11595         if (klass->method.count != gklass->method.count) {
11596                 klass->method.count = gklass->method.count;
11597                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11598
11599                 for (i = 0; i < klass->method.count; i++) {
11600                         MonoError error;
11601                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11602                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11603                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11604                 }
11605         }
11606
11607         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11608                 klass->interface_count = gklass->interface_count;
11609                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11610                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11611
11612                 for (i = 0; i < gklass->interface_count; ++i) {
11613                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11614                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11615                         mono_metadata_free_type (iface_type);
11616
11617                         ensure_runtime_vtable (klass->interfaces [i]);
11618                 }
11619                 klass->interfaces_inited = 1;
11620         }
11621
11622         if (klass->field.count != gklass->field.count) {
11623                 klass->field.count = gklass->field.count;
11624                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11625
11626                 for (i = 0; i < klass->field.count; i++) {
11627                         klass->fields [i] = gklass->fields [i];
11628                         klass->fields [i].parent = klass;
11629                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11630                 }
11631         }
11632
11633         /*We can only finish with this klass once it's parent has as well*/
11634         if (gklass->wastypebuilder)
11635                 klass->wastypebuilder = TRUE;
11636         return;
11637 }
11638
11639 static void
11640 ensure_generic_class_runtime_vtable (MonoClass *klass)
11641 {
11642         MonoClass *gklass = klass->generic_class->container_class;
11643
11644         ensure_runtime_vtable (gklass); 
11645
11646         fix_partial_generic_class (klass);
11647 }
11648
11649 static void
11650 ensure_runtime_vtable (MonoClass *klass)
11651 {
11652         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11653         int i, num, j;
11654
11655         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11656                 return;
11657         if (klass->parent)
11658                 ensure_runtime_vtable (klass->parent);
11659
11660         if (tb) {
11661                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11662                 num += tb->num_methods;
11663                 klass->method.count = num;
11664                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11665                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11666                 for (i = 0; i < num; ++i)
11667                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11668                 num = tb->num_methods;
11669                 j = i;
11670                 for (i = 0; i < num; ++i)
11671                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11672         
11673                 if (tb->interfaces) {
11674                         klass->interface_count = mono_array_length (tb->interfaces);
11675                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11676                         for (i = 0; i < klass->interface_count; ++i) {
11677                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11678                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11679                                 ensure_runtime_vtable (klass->interfaces [i]);
11680                         }
11681                         klass->interfaces_inited = 1;
11682                 }
11683         } else if (klass->generic_class){
11684                 ensure_generic_class_runtime_vtable (klass);
11685         }
11686
11687         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11688                 int slot_num = 0;
11689                 for (i = 0; i < klass->method.count; ++i) {
11690                         MonoMethod *im = klass->methods [i];
11691                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11692                                 im->slot = slot_num++;
11693                 }
11694                 
11695                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11696                 mono_class_setup_interface_offsets (klass);
11697                 mono_class_setup_interface_id (klass);
11698         }
11699
11700         /*
11701          * The generic vtable is needed even if image->run is not set since some
11702          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11703          * method->slot being defined.
11704          */
11705
11706         /* 
11707          * tb->methods could not be freed since it is used for determining 
11708          * overrides during dynamic vtable construction.
11709          */
11710 }
11711
11712 static MonoMethod*
11713 mono_reflection_method_get_handle (MonoObject *method)
11714 {
11715         MonoClass *klass = mono_object_class (method);
11716         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11717                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11718                 return sr_method->method;
11719         }
11720         if (is_sre_method_builder (klass)) {
11721                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11722                 return mb->mhandle;
11723         }
11724         if (is_sre_method_on_tb_inst (klass)) {
11725                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11726                 MonoMethod *result;
11727                 /*FIXME move this to a proper method and unify with resolve_object*/
11728                 if (m->method_args) {
11729                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11730                 } else {
11731                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11732                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11733                         MonoMethod *mono_method;
11734
11735                         if (is_sre_method_builder (mono_object_class (m->mb)))
11736                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11737                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11738                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11739                         else
11740                                 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)));
11741
11742                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11743                 }
11744                 return result;
11745         }
11746
11747         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11748         return NULL;
11749 }
11750
11751 void
11752 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11753 {
11754         MonoReflectionTypeBuilder *tb;
11755         int i, j, onum;
11756         MonoReflectionMethod *m;
11757
11758         *overrides = NULL;
11759         *num_overrides = 0;
11760
11761         g_assert (image_is_dynamic (klass->image));
11762
11763         if (!mono_class_get_ref_info (klass))
11764                 return;
11765
11766         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11767
11768         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11769
11770         onum = 0;
11771         if (tb->methods) {
11772                 for (i = 0; i < tb->num_methods; ++i) {
11773                         MonoReflectionMethodBuilder *mb = 
11774                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11775                         if (mb->override_methods)
11776                                 onum += mono_array_length (mb->override_methods);
11777                 }
11778         }
11779
11780         if (onum) {
11781                 *overrides = g_new0 (MonoMethod*, onum * 2);
11782
11783                 onum = 0;
11784                 for (i = 0; i < tb->num_methods; ++i) {
11785                         MonoReflectionMethodBuilder *mb = 
11786                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11787                         if (mb->override_methods) {
11788                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11789                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11790
11791                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11792                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11793
11794                                         g_assert (mb->mhandle);
11795
11796                                         onum ++;
11797                                 }
11798                         }
11799                 }
11800         }
11801
11802         *num_overrides = onum;
11803 }
11804
11805 static void
11806 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11807 {
11808         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11809         MonoReflectionFieldBuilder *fb;
11810         MonoClassField *field;
11811         MonoImage *image = klass->image;
11812         const char *p, *p2;
11813         int i;
11814         guint32 len, idx, real_size = 0;
11815
11816         klass->field.count = tb->num_fields;
11817         klass->field.first = 0;
11818
11819         mono_error_init (error);
11820
11821         if (tb->class_size) {
11822                 if ((tb->packing_size & 0xffffff00) != 0) {
11823                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11824                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11825                         return;
11826                 }
11827                 klass->packing_size = tb->packing_size;
11828                 real_size = klass->instance_size + tb->class_size;
11829         }
11830
11831         if (!klass->field.count) {
11832                 klass->instance_size = MAX (klass->instance_size, real_size);
11833                 return;
11834         }
11835         
11836         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11837         mono_class_alloc_ext (klass);
11838         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11839         /*
11840         This is, guess what, a hack.
11841         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11842         On the static path no field class is resolved, only types are built. This is the right thing to do
11843         but we suck.
11844         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11845         */
11846         klass->size_inited = 1;
11847
11848         for (i = 0; i < klass->field.count; ++i) {
11849                 MonoArray *rva_data;
11850                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11851                 field = &klass->fields [i];
11852                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11853                 if (!mono_error_ok (error))
11854                         return;
11855                 if (fb->attrs) {
11856                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11857                         field->type->attrs = fb->attrs;
11858                 } else {
11859                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11860                 }
11861
11862                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11863                         char *base = mono_array_addr (rva_data, char, 0);
11864                         size_t size = mono_array_length (rva_data);
11865                         char *data = (char *)mono_image_alloc (klass->image, size);
11866                         memcpy (data, base, size);
11867                         klass->ext->field_def_values [i].data = data;
11868                 }
11869                 if (fb->offset != -1)
11870                         field->offset = fb->offset;
11871                 field->parent = klass;
11872                 fb->handle = field;
11873                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11874
11875                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11876                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11877                 }
11878                 if (fb->def_value) {
11879                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11880                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11881                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11882                         /* Copy the data from the blob since it might get realloc-ed */
11883                         p = assembly->blob.data + idx;
11884                         len = mono_metadata_decode_blob_size (p, &p2);
11885                         len += p2 - p;
11886                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11887                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11888                 }
11889         }
11890
11891         klass->instance_size = MAX (klass->instance_size, real_size);
11892         mono_class_layout_fields (klass);
11893 }
11894
11895 static void
11896 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11897 {
11898         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11899         MonoReflectionPropertyBuilder *pb;
11900         MonoImage *image = klass->image;
11901         MonoProperty *properties;
11902         int i;
11903
11904         mono_error_init (error);
11905
11906         if (!klass->ext)
11907                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11908
11909         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11910         klass->ext->property.first = 0;
11911
11912         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11913         klass->ext->properties = properties;
11914         for (i = 0; i < klass->ext->property.count; ++i) {
11915                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11916                 properties [i].parent = klass;
11917                 properties [i].attrs = pb->attrs;
11918                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11919                 if (!mono_error_ok (error))
11920                         return;
11921                 if (pb->get_method)
11922                         properties [i].get = pb->get_method->mhandle;
11923                 if (pb->set_method)
11924                         properties [i].set = pb->set_method->mhandle;
11925
11926                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11927                 if (pb->def_value) {
11928                         guint32 len, idx;
11929                         const char *p, *p2;
11930                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11931                         if (!klass->ext->prop_def_values)
11932                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11933                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11934                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11935                         /* Copy the data from the blob since it might get realloc-ed */
11936                         p = assembly->blob.data + idx;
11937                         len = mono_metadata_decode_blob_size (p, &p2);
11938                         len += p2 - p;
11939                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11940                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11941                 }
11942         }
11943 }
11944
11945 MonoReflectionEvent *
11946 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11947 {
11948         MonoEvent *event = g_new0 (MonoEvent, 1);
11949         MonoClass *klass;
11950
11951         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11952
11953         event->parent = klass;
11954         event->attrs = eb->attrs;
11955         event->name = mono_string_to_utf8 (eb->name);
11956         if (eb->add_method)
11957                 event->add = eb->add_method->mhandle;
11958         if (eb->remove_method)
11959                 event->remove = eb->remove_method->mhandle;
11960         if (eb->raise_method)
11961                 event->raise = eb->raise_method->mhandle;
11962
11963 #ifndef MONO_SMALL_CONFIG
11964         if (eb->other_methods) {
11965                 int j;
11966                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11967                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11968                         MonoReflectionMethodBuilder *mb = 
11969                                 mono_array_get (eb->other_methods,
11970                                                 MonoReflectionMethodBuilder*, j);
11971                         event->other [j] = mb->mhandle;
11972                 }
11973         }
11974 #endif
11975
11976         return mono_event_get_object (mono_object_domain (tb), klass, event);
11977 }
11978
11979 static void
11980 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11981 {
11982         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11983         MonoReflectionEventBuilder *eb;
11984         MonoImage *image = klass->image;
11985         MonoEvent *events;
11986         int i;
11987
11988         mono_error_init (error);
11989
11990         if (!klass->ext)
11991                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11992
11993         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11994         klass->ext->event.first = 0;
11995
11996         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11997         klass->ext->events = events;
11998         for (i = 0; i < klass->ext->event.count; ++i) {
11999                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12000                 events [i].parent = klass;
12001                 events [i].attrs = eb->attrs;
12002                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12003                 if (!mono_error_ok (error))
12004                         return;
12005                 if (eb->add_method)
12006                         events [i].add = eb->add_method->mhandle;
12007                 if (eb->remove_method)
12008                         events [i].remove = eb->remove_method->mhandle;
12009                 if (eb->raise_method)
12010                         events [i].raise = eb->raise_method->mhandle;
12011
12012 #ifndef MONO_SMALL_CONFIG
12013                 if (eb->other_methods) {
12014                         int j;
12015                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12016                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12017                                 MonoReflectionMethodBuilder *mb = 
12018                                         mono_array_get (eb->other_methods,
12019                                                                         MonoReflectionMethodBuilder*, j);
12020                                 events [i].other [j] = mb->mhandle;
12021                         }
12022                 }
12023 #endif
12024                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12025         }
12026 }
12027
12028 static gboolean
12029 remove_instantiations_of_and_ensure_contents (gpointer key,
12030                                                   gpointer value,
12031                                                   gpointer user_data)
12032 {
12033         MonoType *type = (MonoType*)key;
12034         MonoClass *klass = (MonoClass*)user_data;
12035
12036         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12037                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12038                 return TRUE;
12039         } else
12040                 return FALSE;
12041 }
12042
12043 static void
12044 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12045 {
12046         mono_error_init (error);
12047         int i;
12048
12049         if (!arr)
12050                 return;
12051
12052         for (i = 0; i < mono_array_length (arr); ++i) {
12053                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12054                 if (!mono_error_ok (error))
12055                         break;
12056         }
12057 }
12058
12059 MonoReflectionType*
12060 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12061 {
12062         MonoError error;
12063         MonoClass *klass;
12064         MonoDomain* domain;
12065         MonoReflectionType* res;
12066         int i, j;
12067
12068         domain = mono_object_domain (tb);
12069         klass = mono_class_from_mono_type (tb->type.type);
12070
12071         /*
12072          * Check for user defined Type subclasses.
12073          */
12074         RESOLVE_TYPE (tb->parent, &error);
12075         mono_error_raise_exception (&error); /* FIXME don't raise here */
12076         check_array_for_usertypes (tb->interfaces, &error);
12077         mono_error_raise_exception (&error); /*FIXME don't raise here */
12078         if (tb->fields) {
12079                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12080                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12081                         if (fb) {
12082                                 RESOLVE_TYPE (fb->type, &error);
12083                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12084                                 check_array_for_usertypes (fb->modreq, &error);
12085                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12086                                 check_array_for_usertypes (fb->modopt, &error);
12087                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12088                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12089                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12090                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12091                                 }
12092                         }
12093                 }
12094         }
12095         if (tb->methods) {
12096                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12097                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12098                         if (mb) {
12099                                 RESOLVE_TYPE (mb->rtype, &error);
12100                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12101                                 check_array_for_usertypes (mb->return_modreq, &error);
12102                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12103                                 check_array_for_usertypes (mb->return_modopt, &error);
12104                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12105                                 check_array_for_usertypes (mb->parameters, &error);
12106                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12107                                 if (mb->param_modreq)
12108                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12109                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12110                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12111                                         }
12112                                 if (mb->param_modopt)
12113                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12114                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12115                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12116                                         }
12117                         }
12118                 }
12119         }
12120         if (tb->ctors) {
12121                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12122                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12123                         if (mb) {
12124                                 check_array_for_usertypes (mb->parameters, &error);
12125                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12126                                 if (mb->param_modreq)
12127                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12128                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12129                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12130                                         }
12131                                 if (mb->param_modopt)
12132                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12133                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12134                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12135                                         }
12136                         }
12137                 }
12138         }
12139
12140         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12141
12142         /* 
12143          * we need to lock the domain because the lock will be taken inside
12144          * So, we need to keep the locking order correct.
12145          */
12146         mono_loader_lock ();
12147         mono_domain_lock (domain);
12148         if (klass->wastypebuilder) {
12149                 mono_domain_unlock (domain);
12150                 mono_loader_unlock ();
12151
12152                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12153                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12154
12155                 return res;
12156         }
12157         /*
12158          * Fields to set in klass:
12159          * the various flags: delegate/unicode/contextbound etc.
12160          */
12161         klass->flags = tb->attrs;
12162         klass->has_cctor = 1;
12163         klass->has_finalize = 1;
12164         klass->has_finalize_inited = 1;
12165
12166         mono_class_setup_parent (klass, klass->parent);
12167         /* fool mono_class_setup_supertypes */
12168         klass->supertypes = NULL;
12169         mono_class_setup_supertypes (klass);
12170         mono_class_setup_mono_type (klass);
12171
12172 #if 0
12173         if (!((MonoDynamicImage*)klass->image)->run) {
12174                 if (klass->generic_container) {
12175                         /* FIXME: The code below can't handle generic classes */
12176                         klass->wastypebuilder = TRUE;
12177                         mono_loader_unlock ();
12178                         mono_domain_unlock (domain);
12179
12180                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12181                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12182
12183                         return res;
12184                 }
12185         }
12186 #endif
12187
12188         /* enums are done right away */
12189         if (!klass->enumtype)
12190                 ensure_runtime_vtable (klass);
12191
12192         if (tb->subtypes) {
12193                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12194                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12195                         mono_class_alloc_ext (klass);
12196                         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)));
12197                 }
12198         }
12199
12200         klass->nested_classes_inited = TRUE;
12201
12202         /* fields and object layout */
12203         if (klass->parent) {
12204                 if (!klass->parent->size_inited)
12205                         mono_class_init (klass->parent);
12206                 klass->instance_size = klass->parent->instance_size;
12207                 klass->sizes.class_size = 0;
12208                 klass->min_align = klass->parent->min_align;
12209                 /* if the type has no fields we won't call the field_setup
12210                  * routine which sets up klass->has_references.
12211                  */
12212                 klass->has_references |= klass->parent->has_references;
12213         } else {
12214                 klass->instance_size = sizeof (MonoObject);
12215                 klass->min_align = 1;
12216         }
12217
12218         /* FIXME: handle packing_size and instance_size */
12219         typebuilder_setup_fields (klass, &error);
12220         if (!mono_error_ok (&error))
12221                 goto failure;
12222         typebuilder_setup_properties (klass, &error);
12223         if (!mono_error_ok (&error))
12224                 goto failure;
12225
12226         typebuilder_setup_events (klass, &error);
12227         if (!mono_error_ok (&error))
12228                 goto failure;
12229
12230         klass->wastypebuilder = TRUE;
12231
12232         /* 
12233          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12234          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12235          * we want to return normal System.MonoType objects, so clear these out from the cache.
12236          *
12237          * Together with this we must ensure the contents of all instances to match the created type.
12238          */
12239         if (domain->type_hash && klass->generic_container)
12240                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12241
12242         mono_domain_unlock (domain);
12243         mono_loader_unlock ();
12244
12245         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12246                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12247                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12248         }
12249
12250         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12251         mono_error_raise_exception (&error); /* FIXME don't raise here */
12252
12253         g_assert (res != (MonoReflectionType*)tb);
12254
12255         return res;
12256
12257 failure:
12258         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12259         klass->wastypebuilder = TRUE;
12260         mono_domain_unlock (domain);
12261         mono_loader_unlock ();
12262         mono_error_raise_exception (&error);
12263         return NULL;
12264 }
12265
12266 void
12267 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12268 {
12269         MonoGenericParamFull *param;
12270         MonoImage *image;
12271         MonoClass *pklass;
12272         MonoError error;
12273
12274         image = &gparam->tbuilder->module->dynamic_image->image;
12275
12276         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12277
12278         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12279         g_assert (mono_error_ok (&error));
12280         param->param.num = gparam->index;
12281
12282         if (gparam->mbuilder) {
12283                 if (!gparam->mbuilder->generic_container) {
12284                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12285                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12286                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12287                         gparam->mbuilder->generic_container->is_method = TRUE;
12288                         /* 
12289                          * Cannot set owner.method, since the MonoMethod is not created yet.
12290                          * Set the image field instead, so type_in_image () works.
12291                          */
12292                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12293                         gparam->mbuilder->generic_container->owner.image = klass->image;
12294                 }
12295                 param->param.owner = gparam->mbuilder->generic_container;
12296         } else if (gparam->tbuilder) {
12297                 if (!gparam->tbuilder->generic_container) {
12298                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12299                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12300                         gparam->tbuilder->generic_container->owner.klass = klass;
12301                 }
12302                 param->param.owner = gparam->tbuilder->generic_container;
12303         }
12304
12305         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12306
12307         gparam->type.type = &pklass->byval_arg;
12308
12309         mono_class_set_ref_info (pklass, gparam);
12310         mono_image_append_class_to_reflection_info_set (pklass);
12311 }
12312
12313 MonoArray *
12314 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12315 {
12316         MonoError error;
12317         MonoReflectionModuleBuilder *module = sig->module;
12318         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12319         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12320         guint32 buflen, i;
12321         MonoArray *result;
12322         SigBuffer buf;
12323
12324         check_array_for_usertypes (sig->arguments, &error);
12325         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12326
12327         sigbuffer_init (&buf, 32);
12328
12329         sigbuffer_add_value (&buf, 0x07);
12330         sigbuffer_add_value (&buf, na);
12331         if (assembly != NULL){
12332                 for (i = 0; i < na; ++i) {
12333                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12334                         encode_reflection_type (assembly, type, &buf);
12335                 }
12336         }
12337
12338         buflen = buf.p - buf.buf;
12339         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12340         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12341         sigbuffer_free (&buf);
12342
12343         return result;
12344 }
12345
12346 MonoArray *
12347 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12348 {
12349         MonoError error;
12350         MonoDynamicImage *assembly = sig->module->dynamic_image;
12351         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12352         guint32 buflen, i;
12353         MonoArray *result;
12354         SigBuffer buf;
12355
12356         check_array_for_usertypes (sig->arguments, &error);
12357         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12358
12359         sigbuffer_init (&buf, 32);
12360
12361         sigbuffer_add_value (&buf, 0x06);
12362         for (i = 0; i < na; ++i) {
12363                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12364                 encode_reflection_type (assembly, type, &buf);
12365         }
12366
12367         buflen = buf.p - buf.buf;
12368         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12369         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12370         sigbuffer_free (&buf);
12371
12372         return result;
12373 }
12374
12375 typedef struct {
12376         MonoMethod *handle;
12377         MonoDomain *domain;
12378 } DynamicMethodReleaseData;
12379
12380 /*
12381  * The runtime automatically clean up those after finalization.
12382 */      
12383 static MonoReferenceQueue *dynamic_method_queue;
12384
12385 static void
12386 free_dynamic_method (void *dynamic_method)
12387 {
12388         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12389         MonoDomain *domain = data->domain;
12390         MonoMethod *method = data->handle;
12391         guint32 dis_link;
12392
12393         mono_domain_lock (domain);
12394         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12395         g_hash_table_remove (domain->method_to_dyn_method, method);
12396         mono_domain_unlock (domain);
12397         g_assert (dis_link);
12398         mono_gchandle_free (dis_link);
12399
12400         mono_runtime_free_method (domain, method);
12401         g_free (data);
12402 }
12403
12404 void 
12405 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12406 {
12407         MonoReferenceQueue *queue;
12408         MonoMethod *handle;
12409         DynamicMethodReleaseData *release_data;
12410         ReflectionMethodBuilder rmb;
12411         MonoMethodSignature *sig;
12412         MonoClass *klass;
12413         MonoDomain *domain;
12414         GSList *l;
12415         int i;
12416
12417         if (mono_runtime_is_shutting_down ())
12418                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12419
12420         if (!(queue = dynamic_method_queue)) {
12421                 mono_loader_lock ();
12422                 if (!(queue = dynamic_method_queue))
12423                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12424                 mono_loader_unlock ();
12425         }
12426
12427         sig = dynamic_method_to_signature (mb);
12428
12429         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12430
12431         /*
12432          * Resolve references.
12433          */
12434         /* 
12435          * Every second entry in the refs array is reserved for storing handle_class,
12436          * which is needed by the ldtoken implementation in the JIT.
12437          */
12438         rmb.nrefs = mb->nrefs;
12439         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12440         for (i = 0; i < mb->nrefs; i += 2) {
12441                 MonoClass *handle_class;
12442                 gpointer ref;
12443                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12444
12445                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12446                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12447                         /*
12448                          * The referenced DynamicMethod should already be created by the managed
12449                          * code, except in the case of circular references. In that case, we store
12450                          * method in the refs array, and fix it up later when the referenced 
12451                          * DynamicMethod is created.
12452                          */
12453                         if (method->mhandle) {
12454                                 ref = method->mhandle;
12455                         } else {
12456                                 /* FIXME: GC object stored in unmanaged memory */
12457                                 ref = method;
12458
12459                                 /* FIXME: GC object stored in unmanaged memory */
12460                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12461                         }
12462                         handle_class = mono_defaults.methodhandle_class;
12463                 } else {
12464                         MonoException *ex = NULL;
12465                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12466                         if (!ref)
12467                                 ex = mono_get_exception_type_load (NULL, NULL);
12468                         else if (mono_security_core_clr_enabled ())
12469                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12470
12471                         if (ex) {
12472                                 g_free (rmb.refs);
12473                                 mono_raise_exception (ex);
12474                                 return;
12475                         }
12476                 }
12477
12478                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12479                 rmb.refs [i + 1] = handle_class;
12480         }               
12481
12482         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12483
12484         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12485         release_data = g_new (DynamicMethodReleaseData, 1);
12486         release_data->handle = handle;
12487         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12488         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12489                 g_free (release_data);
12490
12491         /* Fix up refs entries pointing at us */
12492         for (l = mb->referenced_by; l; l = l->next) {
12493                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12494                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12495                 gpointer *data;
12496                 
12497                 g_assert (method->mhandle);
12498
12499                 data = (gpointer*)wrapper->method_data;
12500                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12501                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12502                                 data [i + 1] = mb->mhandle;
12503                 }
12504         }
12505         g_slist_free (mb->referenced_by);
12506
12507         g_free (rmb.refs);
12508
12509         /* ilgen is no longer needed */
12510         mb->ilgen = NULL;
12511
12512         domain = mono_domain_get ();
12513         mono_domain_lock (domain);
12514         if (!domain->method_to_dyn_method)
12515                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12516         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12517         mono_domain_unlock (domain);
12518 }
12519
12520 #endif /* DISABLE_REFLECTION_EMIT */
12521
12522 /**
12523  * 
12524  * mono_reflection_is_valid_dynamic_token:
12525  * 
12526  * Returns TRUE if token is valid.
12527  * 
12528  */
12529 gboolean
12530 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12531 {
12532         return lookup_dyn_token (image, token) != NULL;
12533 }
12534
12535 MonoMethodSignature *
12536 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12537 {
12538         MonoMethodSignature *sig;
12539         g_assert (image_is_dynamic (image));
12540
12541         mono_error_init (error);
12542
12543         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12544         if (sig)
12545                 return sig;
12546
12547         return mono_method_signature_checked (method, error);
12548 }
12549
12550 #ifndef DISABLE_REFLECTION_EMIT
12551
12552 /**
12553  * mono_reflection_lookup_dynamic_token:
12554  *
12555  * Finish the Builder object pointed to by TOKEN and return the corresponding
12556  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12557  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12558  * mapping table.
12559  *
12560  * LOCKING: Take the loader lock
12561  */
12562 gpointer
12563 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12564 {
12565         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12566         MonoObject *obj;
12567         MonoClass *klass;
12568
12569         obj = lookup_dyn_token (assembly, token);
12570         if (!obj) {
12571                 if (valid_token)
12572                         g_error ("Could not find required dynamic token 0x%08x", token);
12573                 else
12574                         return NULL;
12575         }
12576
12577         if (!handle_class)
12578                 handle_class = &klass;
12579         return resolve_object (image, obj, handle_class, context);
12580 }
12581
12582 /*
12583  * ensure_complete_type:
12584  *
12585  *   Ensure that KLASS is completed if it is a dynamic type, or references
12586  * dynamic types.
12587  */
12588 static void
12589 ensure_complete_type (MonoClass *klass)
12590 {
12591         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12592                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12593
12594                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12595
12596                 // Asserting here could break a lot of code
12597                 //g_assert (klass->wastypebuilder);
12598         }
12599
12600         if (klass->generic_class) {
12601                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12602                 int i;
12603
12604                 for (i = 0; i < inst->type_argc; ++i) {
12605                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12606                 }
12607         }
12608 }
12609
12610 static gpointer
12611 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12612 {
12613         gpointer result = NULL;
12614
12615         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12616                 result = mono_string_intern ((MonoString*)obj);
12617                 *handle_class = mono_defaults.string_class;
12618                 g_assert (result);
12619         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12620                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12621                 MonoClass *mc = mono_class_from_mono_type (type);
12622                 if (!mono_class_init (mc))
12623                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12624
12625                 if (context) {
12626                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12627                         result = mono_class_from_mono_type (inflated);
12628                         mono_metadata_free_type (inflated);
12629                 } else {
12630                         result = mono_class_from_mono_type (type);
12631                 }
12632                 *handle_class = mono_defaults.typehandle_class;
12633                 g_assert (result);
12634         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12635                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12636                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12637                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12638                 result = ((MonoReflectionMethod*)obj)->method;
12639                 if (context) {
12640                         MonoError error;
12641                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12642                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12643                 }
12644                 *handle_class = mono_defaults.methodhandle_class;
12645                 g_assert (result);
12646         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12647                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12648                 result = mb->mhandle;
12649                 if (!result) {
12650                         /* Type is not yet created */
12651                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12652
12653                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12654
12655                         /*
12656                          * Hopefully this has been filled in by calling CreateType() on the
12657                          * TypeBuilder.
12658                          */
12659                         /*
12660                          * TODO: This won't work if the application finishes another 
12661                          * TypeBuilder instance instead of this one.
12662                          */
12663                         result = mb->mhandle;
12664                 }
12665                 if (context) {
12666                         MonoError error;
12667                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12668                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12669                 }
12670                 *handle_class = mono_defaults.methodhandle_class;
12671         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12672                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12673
12674                 result = cb->mhandle;
12675                 if (!result) {
12676                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12677
12678                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12679                         result = cb->mhandle;
12680                 }
12681                 if (context) {
12682                         MonoError error;
12683                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12684                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12685                 }
12686                 *handle_class = mono_defaults.methodhandle_class;
12687         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12688                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12689
12690                 ensure_complete_type (field->parent);
12691                 if (context) {
12692                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12693                         MonoClass *klass = mono_class_from_mono_type (inflated);
12694                         MonoClassField *inflated_field;
12695                         gpointer iter = NULL;
12696                         mono_metadata_free_type (inflated);
12697                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12698                                 if (!strcmp (field->name, inflated_field->name))
12699                                         break;
12700                         }
12701                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12702                         result = inflated_field;
12703                 } else {
12704                         result = field;
12705                 }
12706                 *handle_class = mono_defaults.fieldhandle_class;
12707                 g_assert (result);
12708         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12709                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12710                 result = fb->handle;
12711
12712                 if (!result) {
12713                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12714
12715                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12716                         result = fb->handle;
12717                 }
12718
12719                 if (fb->handle && fb->handle->parent->generic_container) {
12720                         MonoClass *klass = fb->handle->parent;
12721                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12722                         MonoClass *inflated = mono_class_from_mono_type (type);
12723
12724                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12725                         g_assert (result);
12726                         mono_metadata_free_type (type);
12727                 }
12728                 *handle_class = mono_defaults.fieldhandle_class;
12729         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12730                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12731                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12732                 MonoClass *klass;
12733
12734                 klass = type->data.klass;
12735                 if (klass->wastypebuilder) {
12736                         /* Already created */
12737                         result = klass;
12738                 }
12739                 else {
12740                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12741                         result = type->data.klass;
12742                         g_assert (result);
12743                 }
12744                 *handle_class = mono_defaults.typehandle_class;
12745         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12746                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12747                 MonoMethodSignature *sig;
12748                 int nargs, i;
12749
12750                 if (helper->arguments)
12751                         nargs = mono_array_length (helper->arguments);
12752                 else
12753                         nargs = 0;
12754
12755                 sig = mono_metadata_signature_alloc (image, nargs);
12756                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12757                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12758
12759                 if (helper->unmanaged_call_conv) { /* unmanaged */
12760                         sig->call_convention = helper->unmanaged_call_conv - 1;
12761                         sig->pinvoke = TRUE;
12762                 } else if (helper->call_conv & 0x02) {
12763                         sig->call_convention = MONO_CALL_VARARG;
12764                 } else {
12765                         sig->call_convention = MONO_CALL_DEFAULT;
12766                 }
12767
12768                 sig->param_count = nargs;
12769                 /* TODO: Copy type ? */
12770                 sig->ret = helper->return_type->type;
12771                 for (i = 0; i < nargs; ++i)
12772                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12773
12774                 result = sig;
12775                 *handle_class = NULL;
12776         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12777                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12778                 /* Already created by the managed code */
12779                 g_assert (method->mhandle);
12780                 result = method->mhandle;
12781                 *handle_class = mono_defaults.methodhandle_class;
12782         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12783                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12784                 type = mono_class_inflate_generic_type (type, context);
12785                 result = mono_class_from_mono_type (type);
12786                 *handle_class = mono_defaults.typehandle_class;
12787                 g_assert (result);
12788                 mono_metadata_free_type (type);
12789         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12790                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12791                 type = mono_class_inflate_generic_type (type, context);
12792                 result = mono_class_from_mono_type (type);
12793                 *handle_class = mono_defaults.typehandle_class;
12794                 g_assert (result);
12795                 mono_metadata_free_type (type);
12796         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12797                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12798                 MonoClass *inflated;
12799                 MonoType *type;
12800                 MonoClassField *field;
12801
12802                 if (is_sre_field_builder (mono_object_class (f->fb)))
12803                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12804                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12805                         field = ((MonoReflectionField*)f->fb)->field;
12806                 else
12807                         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)));
12808
12809                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12810                 inflated = mono_class_from_mono_type (type);
12811
12812                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12813                 ensure_complete_type (field->parent);
12814                 g_assert (result);
12815                 mono_metadata_free_type (type);
12816                 *handle_class = mono_defaults.fieldhandle_class;
12817         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12818                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12819                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12820                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12821                 MonoMethod *method;
12822
12823                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12824                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12825                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12826                         method = ((MonoReflectionMethod *)c->cb)->method;
12827                 else
12828                         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)));
12829
12830                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12831                 *handle_class = mono_defaults.methodhandle_class;
12832                 mono_metadata_free_type (type);
12833         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12834                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12835                 if (m->method_args) {
12836                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12837                         if (context) {
12838                                 MonoError error;
12839                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12840                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12841                         }
12842                 } else {
12843                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12844                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12845                         MonoMethod *method;
12846
12847                         if (is_sre_method_builder (mono_object_class (m->mb)))
12848                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12849                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12850                                 method = ((MonoReflectionMethod *)m->mb)->method;
12851                         else
12852                                 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)));
12853
12854                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12855                         mono_metadata_free_type (type);
12856                 }
12857                 *handle_class = mono_defaults.methodhandle_class;
12858         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12859                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12860                 MonoType *mtype;
12861                 MonoClass *klass;
12862                 MonoMethod *method;
12863                 gpointer iter;
12864                 char *name;
12865
12866                 mtype = mono_reflection_type_get_handle (m->parent);
12867                 klass = mono_class_from_mono_type (mtype);
12868
12869                 /* Find the method */
12870
12871                 name = mono_string_to_utf8 (m->name);
12872                 iter = NULL;
12873                 while ((method = mono_class_get_methods (klass, &iter))) {
12874                         if (!strcmp (method->name, name))
12875                                 break;
12876                 }
12877                 g_free (name);
12878
12879                 // FIXME:
12880                 g_assert (method);
12881                 // FIXME: Check parameters/return value etc. match
12882
12883                 result = method;
12884                 *handle_class = mono_defaults.methodhandle_class;
12885         } else if (is_sre_array (mono_object_get_class(obj)) ||
12886                                 is_sre_byref (mono_object_get_class(obj)) ||
12887                                 is_sre_pointer (mono_object_get_class(obj))) {
12888                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12889                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12890
12891                 if (context) {
12892                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12893                         result = mono_class_from_mono_type (inflated);
12894                         mono_metadata_free_type (inflated);
12895                 } else {
12896                         result = mono_class_from_mono_type (type);
12897                 }
12898                 *handle_class = mono_defaults.typehandle_class;
12899         } else {
12900                 g_print ("%s\n", obj->vtable->klass->name);
12901                 g_assert_not_reached ();
12902         }
12903         return result;
12904 }
12905
12906 #else /* DISABLE_REFLECTION_EMIT */
12907
12908 MonoArray*
12909 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12910 {
12911         g_assert_not_reached ();
12912         return NULL;
12913 }
12914
12915 void
12916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12917 {
12918         g_assert_not_reached ();
12919 }
12920
12921 void
12922 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12923 {
12924         g_assert_not_reached ();
12925 }
12926
12927 void
12928 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12929 {
12930         g_assert_not_reached ();
12931 }
12932
12933 void
12934 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12935 {
12936         g_assert_not_reached ();
12937 }
12938
12939 void
12940 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12941 {
12942         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12943 }
12944
12945 void
12946 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12947 {
12948         g_assert_not_reached ();
12949 }
12950
12951 void
12952 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12953 {
12954         g_assert_not_reached ();
12955 }
12956
12957 MonoReflectionModule *
12958 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12959 {
12960         g_assert_not_reached ();
12961         return NULL;
12962 }
12963
12964 guint32
12965 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12966 {
12967         g_assert_not_reached ();
12968         return 0;
12969 }
12970
12971 guint32
12972 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
12973 {
12974         g_assert_not_reached ();
12975         return 0;
12976 }
12977
12978 guint32
12979 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12980                                                  gboolean create_open_instance, gboolean register_token)
12981 {
12982         g_assert_not_reached ();
12983         return 0;
12984 }
12985
12986 void
12987 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12988 {
12989 }
12990
12991 void
12992 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12993 {
12994         g_assert_not_reached ();
12995 }
12996
12997 void
12998 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12999 {
13000         *overrides = NULL;
13001         *num_overrides = 0;
13002 }
13003
13004 MonoReflectionEvent *
13005 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13006 {
13007         g_assert_not_reached ();
13008         return NULL;
13009 }
13010
13011 MonoReflectionType*
13012 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13013 {
13014         g_assert_not_reached ();
13015         return NULL;
13016 }
13017
13018 void
13019 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13020 {
13021         g_assert_not_reached ();
13022 }
13023
13024 MonoArray *
13025 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13026 {
13027         g_assert_not_reached ();
13028         return NULL;
13029 }
13030
13031 MonoArray *
13032 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13033 {
13034         g_assert_not_reached ();
13035         return NULL;
13036 }
13037
13038 void 
13039 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13040 {
13041 }
13042
13043 gpointer
13044 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13045 {
13046         return NULL;
13047 }
13048
13049 MonoType*
13050 mono_reflection_type_get_handle (MonoReflectionType* ref)
13051 {
13052         if (!ref)
13053                 return NULL;
13054         return ref->type;
13055 }
13056
13057 void
13058 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13059 {
13060         g_assert_not_reached ();
13061 }
13062
13063 #endif /* DISABLE_REFLECTION_EMIT */
13064
13065 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13066 const static guint32 declsec_flags_map[] = {
13067         0x00000000,                                     /* empty */
13068         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13069         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13070         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13071         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13072         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13073         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13074         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13075         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13076         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13077         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13078         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13079         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13080         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13081         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13082         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13083         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13084         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13085         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13086 };
13087
13088 /*
13089  * Returns flags that includes all available security action associated to the handle.
13090  * @token: metadata token (either for a class or a method)
13091  * @image: image where resides the metadata.
13092  */
13093 static guint32
13094 mono_declsec_get_flags (MonoImage *image, guint32 token)
13095 {
13096         int index = mono_metadata_declsec_from_index (image, token);
13097         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13098         guint32 result = 0;
13099         guint32 action;
13100         int i;
13101
13102         /* HasSecurity can be present for other, not specially encoded, attributes,
13103            e.g. SuppressUnmanagedCodeSecurityAttribute */
13104         if (index < 0)
13105                 return 0;
13106
13107         for (i = index; i < t->rows; i++) {
13108                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13109
13110                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13111                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13112                         break;
13113
13114                 action = cols [MONO_DECL_SECURITY_ACTION];
13115                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13116                         result |= declsec_flags_map [action];
13117                 } else {
13118                         g_assert_not_reached ();
13119                 }
13120         }
13121         return result;
13122 }
13123
13124 /*
13125  * Get the security actions (in the form of flags) associated with the specified method.
13126  *
13127  * @method: The method for which we want the declarative security flags.
13128  * Return the declarative security flags for the method (only).
13129  *
13130  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13131  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13132  */
13133 guint32
13134 mono_declsec_flags_from_method (MonoMethod *method)
13135 {
13136         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13137                 /* FIXME: No cache (for the moment) */
13138                 guint32 idx = mono_method_get_index (method);
13139                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13140                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13141                 return mono_declsec_get_flags (method->klass->image, idx);
13142         }
13143         return 0;
13144 }
13145
13146 /*
13147  * Get the security actions (in the form of flags) associated with the specified class.
13148  *
13149  * @klass: The class for which we want the declarative security flags.
13150  * Return the declarative security flags for the class.
13151  *
13152  * Note: We cache the flags inside the MonoClass structure as this will get 
13153  *       called very often (at least for each method).
13154  */
13155 guint32
13156 mono_declsec_flags_from_class (MonoClass *klass)
13157 {
13158         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13159                 if (!klass->ext || !klass->ext->declsec_flags) {
13160                         guint32 idx;
13161
13162                         idx = mono_metadata_token_index (klass->type_token);
13163                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13164                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13165                         mono_loader_lock ();
13166                         mono_class_alloc_ext (klass);
13167                         mono_loader_unlock ();
13168                         /* we cache the flags on classes */
13169                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13170                 }
13171                 return klass->ext->declsec_flags;
13172         }
13173         return 0;
13174 }
13175
13176 /*
13177  * Get the security actions (in the form of flags) associated with the specified assembly.
13178  *
13179  * @assembly: The assembly for which we want the declarative security flags.
13180  * Return the declarative security flags for the assembly.
13181  */
13182 guint32
13183 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13184 {
13185         guint32 idx = 1; /* there is only one assembly */
13186         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13187         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13188         return mono_declsec_get_flags (assembly->image, idx);
13189 }
13190
13191
13192 /*
13193  * Fill actions for the specific index (which may either be an encoded class token or
13194  * an encoded method token) from the metadata image.
13195  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13196  */
13197 static MonoBoolean
13198 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13199         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13200 {
13201         MonoBoolean result = FALSE;
13202         MonoTableInfo *t;
13203         guint32 cols [MONO_DECL_SECURITY_SIZE];
13204         int index = mono_metadata_declsec_from_index (image, token);
13205         int i;
13206
13207         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13208         for (i = index; i < t->rows; i++) {
13209                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13210
13211                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13212                         return result;
13213
13214                 /* if present only replace (class) permissions with method permissions */
13215                 /* if empty accept either class or method permissions */
13216                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13217                         if (!actions->demand.blob) {
13218                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13219                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13220                                 actions->demand.blob = (char*) (blob + 2);
13221                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13222                                 result = TRUE;
13223                         }
13224                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13225                         if (!actions->noncasdemand.blob) {
13226                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13227                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13228                                 actions->noncasdemand.blob = (char*) (blob + 2);
13229                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13230                                 result = TRUE;
13231                         }
13232                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13233                         if (!actions->demandchoice.blob) {
13234                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13235                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13236                                 actions->demandchoice.blob = (char*) (blob + 2);
13237                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13238                                 result = TRUE;
13239                         }
13240                 }
13241         }
13242
13243         return result;
13244 }
13245
13246 static MonoBoolean
13247 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13248         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13249 {
13250         guint32 idx = mono_metadata_token_index (klass->type_token);
13251         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13252         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13253         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13254 }
13255
13256 static MonoBoolean
13257 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13258         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13259 {
13260         guint32 idx = mono_method_get_index (method);
13261         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13262         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13263         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13264 }
13265
13266 /*
13267  * Collect all actions (that requires to generate code in mini) assigned for
13268  * the specified method.
13269  * Note: Don't use the content of actions if the function return FALSE.
13270  */
13271 MonoBoolean
13272 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13273 {
13274         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13275                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13276         MonoBoolean result = FALSE;
13277         guint32 flags;
13278
13279         /* quick exit if no declarative security is present in the metadata */
13280         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13281                 return FALSE;
13282
13283         /* we want the original as the wrapper is "free" of the security informations */
13284         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13285                 method = mono_marshal_method_from_wrapper (method);
13286                 if (!method)
13287                         return FALSE;
13288         }
13289
13290         /* First we look for method-level attributes */
13291         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13292                 mono_class_init (method->klass);
13293                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13294
13295                 result = mono_declsec_get_method_demands_params (method, demands, 
13296                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13297         }
13298
13299         /* Here we use (or create) the class declarative cache to look for demands */
13300         flags = mono_declsec_flags_from_class (method->klass);
13301         if (flags & mask) {
13302                 if (!result) {
13303                         mono_class_init (method->klass);
13304                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13305                 }
13306                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13307                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13308         }
13309
13310         /* The boolean return value is used as a shortcut in case nothing needs to
13311            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13312         return result;
13313 }
13314
13315
13316 /*
13317  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13318  *
13319  * Note: Don't use the content of actions if the function return FALSE.
13320  */
13321 MonoBoolean
13322 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13323 {
13324         MonoBoolean result = FALSE;
13325         guint32 flags;
13326
13327         /* quick exit if no declarative security is present in the metadata */
13328         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13329                 return FALSE;
13330
13331         /* we want the original as the wrapper is "free" of the security informations */
13332         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13333                 method = mono_marshal_method_from_wrapper (method);
13334                 if (!method)
13335                         return FALSE;
13336         }
13337
13338         /* results are independant - zeroize both */
13339         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13340         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13341
13342         /* First we look for method-level attributes */
13343         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13344                 mono_class_init (method->klass);
13345
13346                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13347                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13348         }
13349
13350         /* Here we use (or create) the class declarative cache to look for demands */
13351         flags = mono_declsec_flags_from_class (method->klass);
13352         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13353                 mono_class_init (method->klass);
13354
13355                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13356                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13357         }
13358
13359         return result;
13360 }
13361
13362 /*
13363  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13364  *
13365  * @klass       The inherited class - this is the class that provides the security check (attributes)
13366  * @demans      
13367  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13368  * 
13369  * Note: Don't use the content of actions if the function return FALSE.
13370  */
13371 MonoBoolean
13372 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13373 {
13374         MonoBoolean result = FALSE;
13375         guint32 flags;
13376
13377         /* quick exit if no declarative security is present in the metadata */
13378         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13379                 return FALSE;
13380
13381         /* Here we use (or create) the class declarative cache to look for demands */
13382         flags = mono_declsec_flags_from_class (klass);
13383         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13384                 mono_class_init (klass);
13385                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13386
13387                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13388                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13389         }
13390
13391         return result;
13392 }
13393
13394 /*
13395  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13396  *
13397  * Note: Don't use the content of actions if the function return FALSE.
13398  */
13399 MonoBoolean
13400 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13401 {
13402         /* quick exit if no declarative security is present in the metadata */
13403         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13404                 return FALSE;
13405
13406         /* we want the original as the wrapper is "free" of the security informations */
13407         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13408                 method = mono_marshal_method_from_wrapper (method);
13409                 if (!method)
13410                         return FALSE;
13411         }
13412
13413         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13414                 mono_class_init (method->klass);
13415                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13416
13417                 return mono_declsec_get_method_demands_params (method, demands, 
13418                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13419         }
13420         return FALSE;
13421 }
13422
13423
13424 static MonoBoolean
13425 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13426 {
13427         guint32 cols [MONO_DECL_SECURITY_SIZE];
13428         MonoTableInfo *t;
13429         int i;
13430
13431         int index = mono_metadata_declsec_from_index (image, token);
13432         if (index == -1)
13433                 return FALSE;
13434
13435         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13436         for (i = index; i < t->rows; i++) {
13437                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13438
13439                 /* shortcut - index are ordered */
13440                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13441                         return FALSE;
13442
13443                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13444                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13445                         entry->blob = (char*) (metadata + 2);
13446                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13447                         return TRUE;
13448                 }
13449         }
13450
13451         return FALSE;
13452 }
13453
13454 MonoBoolean
13455 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13456 {
13457         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13458                 guint32 idx = mono_method_get_index (method);
13459                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13460                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13461                 return get_declsec_action (method->klass->image, idx, action, entry);
13462         }
13463         return FALSE;
13464 }
13465
13466 MonoBoolean
13467 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13468 {
13469         /* use cache */
13470         guint32 flags = mono_declsec_flags_from_class (klass);
13471         if (declsec_flags_map [action] & flags) {
13472                 guint32 idx = mono_metadata_token_index (klass->type_token);
13473                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13474                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13475                 return get_declsec_action (klass->image, idx, action, entry);
13476         }
13477         return FALSE;
13478 }
13479
13480 MonoBoolean
13481 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13482 {
13483         guint32 idx = 1; /* there is only one assembly */
13484         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13485         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13486
13487         return get_declsec_action (assembly->image, idx, action, entry);
13488 }
13489
13490 gboolean
13491 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13492 {
13493         MonoError error;
13494         MonoObject *res, *exc;
13495         void *params [1];
13496         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13497         static MonoMethod *method = NULL;
13498
13499         if (!System_Reflection_Emit_TypeBuilder) {
13500                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13501                 g_assert (System_Reflection_Emit_TypeBuilder);
13502         }
13503         if (method == NULL) {
13504                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13505                 g_assert (method);
13506         }
13507
13508         /* 
13509          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13510          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13511          */
13512         g_assert (mono_class_get_ref_info (klass));
13513         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13514
13515         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13516         mono_error_raise_exception (&error); /* FIXME don't raise here */
13517
13518         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13519         if (exc)
13520                 return FALSE;
13521         else
13522                 return *(MonoBoolean*)mono_object_unbox (res);
13523 }
13524
13525 /**
13526  * mono_reflection_type_get_type:
13527  * @reftype: the System.Type object
13528  *
13529  * Returns the MonoType* associated with the C# System.Type object @reftype.
13530  */
13531 MonoType*
13532 mono_reflection_type_get_type (MonoReflectionType *reftype)
13533 {
13534         g_assert (reftype);
13535
13536         return mono_reflection_type_get_handle (reftype);
13537 }
13538
13539 /**
13540  * mono_reflection_assembly_get_assembly:
13541  * @refassembly: the System.Reflection.Assembly object
13542  *
13543  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13544  */
13545 MonoAssembly*
13546 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13547 {
13548         g_assert (refassembly);
13549
13550         return refassembly->assembly;
13551 }
13552