[runtime] Switch to mono_method_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 static guint32
1148 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1149 {
1150         MONO_REQ_GC_UNSAFE_MODE;
1151
1152         char flags = 0;
1153         guint32 idx;
1154         guint32 code_size;
1155         gint32 max_stack, i;
1156         gint32 num_locals = 0;
1157         gint32 num_exception = 0;
1158         gint maybe_small;
1159         guint32 fat_flags;
1160         char fat_header [12];
1161         guint32 int_value;
1162         guint16 short_value;
1163         guint32 local_sig = 0;
1164         guint32 header_size = 12;
1165         MonoArray *code;
1166
1167         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1168                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1169                 return 0;
1170
1171         /*if (mb->name)
1172                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1173         if (mb->ilgen) {
1174                 code = mb->ilgen->code;
1175                 code_size = mb->ilgen->code_len;
1176                 max_stack = mb->ilgen->max_stack;
1177                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1178                 if (mb->ilgen->ex_handlers)
1179                         num_exception = method_count_clauses (mb->ilgen);
1180         } else {
1181                 code = mb->code;
1182                 if (code == NULL){
1183                         char *name = mono_string_to_utf8 (mb->name);
1184                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1185                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1186                         g_free (str);
1187                         g_free (name);
1188                         mono_raise_exception (exception);
1189                 }
1190
1191                 code_size = mono_array_length (code);
1192                 max_stack = 8; /* we probably need to run a verifier on the code... */
1193         }
1194
1195         stream_data_align (&assembly->code);
1196
1197         /* check for exceptions, maxstack, locals */
1198         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1199         if (maybe_small) {
1200                 if (code_size < 64 && !(code_size & 1)) {
1201                         flags = (code_size << 2) | 0x2;
1202                 } else if (code_size < 32 && (code_size & 1)) {
1203                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1204                 } else {
1205                         goto fat_header;
1206                 }
1207                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1208                 /* add to the fixup todo list */
1209                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1210                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1211                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1212                 return assembly->text_rva + idx;
1213         } 
1214 fat_header:
1215         if (num_locals)
1216                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1217         /* 
1218          * FIXME: need to set also the header size in fat_flags.
1219          * (and more sects and init locals flags)
1220          */
1221         fat_flags =  0x03;
1222         if (num_exception)
1223                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1224         if (mb->init_locals)
1225                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1226         fat_header [0] = fat_flags;
1227         fat_header [1] = (header_size / 4 ) << 4;
1228         short_value = GUINT16_TO_LE (max_stack);
1229         memcpy (fat_header + 2, &short_value, 2);
1230         int_value = GUINT32_TO_LE (code_size);
1231         memcpy (fat_header + 4, &int_value, 4);
1232         int_value = GUINT32_TO_LE (local_sig);
1233         memcpy (fat_header + 8, &int_value, 4);
1234         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1235         /* add to the fixup todo list */
1236         if (mb->ilgen && mb->ilgen->num_token_fixups)
1237                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1238         
1239         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1240         if (num_exception) {
1241                 unsigned char sheader [4];
1242                 MonoILExceptionInfo * ex_info;
1243                 MonoILExceptionBlock * ex_block;
1244                 int j;
1245
1246                 stream_data_align (&assembly->code);
1247                 /* always use fat format for now */
1248                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1249                 num_exception *= 6 * sizeof (guint32);
1250                 num_exception += 4; /* include the size of the header */
1251                 sheader [1] = num_exception & 0xff;
1252                 sheader [2] = (num_exception >> 8) & 0xff;
1253                 sheader [3] = (num_exception >> 16) & 0xff;
1254                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1255                 /* fat header, so we are already aligned */
1256                 /* reverse order */
1257                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1258                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1259                         if (ex_info->handlers) {
1260                                 int finally_start = ex_info->start + ex_info->len;
1261                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1262                                         guint32 val;
1263                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1264                                         /* the flags */
1265                                         val = GUINT32_TO_LE (ex_block->type);
1266                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1267                                         /* try offset */
1268                                         val = GUINT32_TO_LE (ex_info->start);
1269                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1270                                         /* need fault, too, probably */
1271                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1272                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1273                                         else
1274                                                 val = GUINT32_TO_LE (ex_info->len);
1275                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276                                         /* handler offset */
1277                                         val = GUINT32_TO_LE (ex_block->start);
1278                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1279                                         /* handler len */
1280                                         val = GUINT32_TO_LE (ex_block->len);
1281                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1282                                         finally_start = ex_block->start + ex_block->len;
1283                                         if (ex_block->extype) {
1284                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1285                                         } else {
1286                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1287                                                         val = ex_block->filter_offset;
1288                                                 else
1289                                                         val = 0;
1290                                         }
1291                                         val = GUINT32_TO_LE (val);
1292                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293                                         /*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", 
1294                                                         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);*/
1295                                 }
1296                         } else {
1297                                 g_error ("No clauses for ex info block %d", i);
1298                         }
1299                 }
1300         }
1301         return assembly->text_rva + idx;
1302 }
1303
1304 static guint32
1305 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1306 {
1307         MONO_REQ_GC_NEUTRAL_MODE;
1308
1309         int i;
1310         MonoDynamicTable *table;
1311         guint32 *values;
1312         
1313         table = &assembly->tables [table_idx];
1314
1315         g_assert (col < table->columns);
1316
1317         values = table->values + table->columns;
1318         for (i = 1; i <= table->rows; ++i) {
1319                 if (values [col] == token)
1320                         return i;
1321                 values += table->columns;
1322         }
1323         return 0;
1324 }
1325
1326 /*
1327  * LOCKING: Acquires the loader lock. 
1328  */
1329 static MonoCustomAttrInfo*
1330 lookup_custom_attr (MonoImage *image, gpointer member)
1331 {
1332         MONO_REQ_GC_NEUTRAL_MODE;
1333
1334         MonoCustomAttrInfo* res;
1335
1336         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1337
1338         if (!res)
1339                 return NULL;
1340
1341         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1342         res->cached = 0;
1343         return res;
1344 }
1345
1346 static gboolean
1347 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1348 {
1349         MONO_REQ_GC_UNSAFE_MODE;
1350
1351         /* FIXME: Need to do more checks */
1352         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1353                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1354
1355                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1356                         return FALSE;
1357         }
1358
1359         return TRUE;
1360 }
1361
1362 static MonoCustomAttrInfo*
1363 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1364 {
1365         MONO_REQ_GC_UNSAFE_MODE;
1366
1367         int i, index, count, not_visible;
1368         MonoCustomAttrInfo *ainfo;
1369         MonoReflectionCustomAttr *cattr;
1370
1371         if (!cattrs)
1372                 return NULL;
1373         /* FIXME: check in assembly the Run flag is set */
1374
1375         count = mono_array_length (cattrs);
1376
1377         /* Skip nonpublic attributes since MS.NET seems to do the same */
1378         /* FIXME: This needs to be done more globally */
1379         not_visible = 0;
1380         for (i = 0; i < count; ++i) {
1381                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1382                 if (!custom_attr_visible (image, cattr))
1383                         not_visible ++;
1384         }
1385         count -= not_visible;
1386
1387         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1388
1389         ainfo->image = image;
1390         ainfo->num_attrs = count;
1391         ainfo->cached = alloc_img != NULL;
1392         index = 0;
1393         for (i = 0; i < count; ++i) {
1394                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1395                 if (custom_attr_visible (image, cattr)) {
1396                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1397                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1398                         ainfo->attrs [index].ctor = cattr->ctor->method;
1399                         ainfo->attrs [index].data = saved;
1400                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1401                         index ++;
1402                 }
1403         }
1404
1405         return ainfo;
1406 }
1407
1408 #ifndef DISABLE_REFLECTION_EMIT
1409 /*
1410  * LOCKING: Acquires the loader lock. 
1411  */
1412 static void
1413 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1414 {
1415         MONO_REQ_GC_UNSAFE_MODE;
1416
1417         MonoCustomAttrInfo *ainfo, *tmp;
1418
1419         if (!cattrs || !mono_array_length (cattrs))
1420                 return;
1421
1422         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1423
1424         mono_loader_lock ();
1425         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1426         if (tmp)
1427                 mono_custom_attrs_free (tmp);
1428         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1429         mono_loader_unlock ();
1430
1431 }
1432 #endif
1433
1434 void
1435 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1436 {
1437         MONO_REQ_GC_NEUTRAL_MODE;
1438
1439         if (!ainfo->cached)
1440                 g_free (ainfo);
1441 }
1442
1443 /*
1444  * idx is the table index of the object
1445  * type is one of MONO_CUSTOM_ATTR_*
1446  */
1447 static void
1448 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1449 {
1450         MONO_REQ_GC_UNSAFE_MODE;
1451
1452         MonoDynamicTable *table;
1453         MonoReflectionCustomAttr *cattr;
1454         guint32 *values;
1455         guint32 count, i, token;
1456         char blob_size [6];
1457         char *p = blob_size;
1458         
1459         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1460         if (!cattrs)
1461                 return;
1462         count = mono_array_length (cattrs);
1463         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1464         table->rows += count;
1465         alloc_table (table, table->rows);
1466         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1467         idx <<= MONO_CUSTOM_ATTR_BITS;
1468         idx |= type;
1469         for (i = 0; i < count; ++i) {
1470                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1472                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1473                 type = mono_metadata_token_index (token);
1474                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1475                 switch (mono_metadata_token_table (token)) {
1476                 case MONO_TABLE_METHOD:
1477                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1478                         /*
1479                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1480                          * method, not the one returned by mono_image_create_token ().
1481                          */
1482                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1483                         break;
1484                 case MONO_TABLE_MEMBERREF:
1485                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1486                         break;
1487                 default:
1488                         g_warning ("got wrong token in custom attr");
1489                         continue;
1490                 }
1491                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1492                 p = blob_size;
1493                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1494                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1495                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1496                 values += MONO_CUSTOM_ATTR_SIZE;
1497                 ++table->next_idx;
1498         }
1499 }
1500
1501 static void
1502 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1503 {
1504         MONO_REQ_GC_UNSAFE_MODE;
1505
1506         MonoDynamicTable *table;
1507         guint32 *values;
1508         guint32 count, i, idx;
1509         MonoReflectionPermissionSet *perm;
1510
1511         if (!permissions)
1512                 return;
1513
1514         count = mono_array_length (permissions);
1515         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1516         table->rows += count;
1517         alloc_table (table, table->rows);
1518
1519         for (i = 0; i < mono_array_length (permissions); ++i) {
1520                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1521
1522                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1523
1524                 idx = mono_metadata_token_index (parent_token);
1525                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1526                 switch (mono_metadata_token_table (parent_token)) {
1527                 case MONO_TABLE_TYPEDEF:
1528                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1529                         break;
1530                 case MONO_TABLE_METHOD:
1531                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1532                         break;
1533                 case MONO_TABLE_ASSEMBLY:
1534                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1535                         break;
1536                 default:
1537                         g_assert_not_reached ();
1538                 }
1539
1540                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1541                 values [MONO_DECL_SECURITY_PARENT] = idx;
1542                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1543
1544                 ++table->next_idx;
1545         }
1546 }
1547
1548 /*
1549  * Fill in the MethodDef and ParamDef tables for a method.
1550  * This is used for both normal methods and constructors.
1551  */
1552 static void
1553 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1554 {
1555         MONO_REQ_GC_UNSAFE_MODE;
1556
1557         MonoDynamicTable *table;
1558         guint32 *values;
1559         guint i, count;
1560
1561         /* room in this table is already allocated */
1562         table = &assembly->tables [MONO_TABLE_METHOD];
1563         *mb->table_idx = table->next_idx ++;
1564         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1565         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1566         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1567         values [MONO_METHOD_FLAGS] = mb->attrs;
1568         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1569         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1570         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1571         
1572         table = &assembly->tables [MONO_TABLE_PARAM];
1573         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1574
1575         mono_image_add_decl_security (assembly, 
1576                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1577
1578         if (mb->pinfo) {
1579                 MonoDynamicTable *mtable;
1580                 guint32 *mvalues;
1581                 
1582                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1583                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1584                 
1585                 count = 0;
1586                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1587                         if (mono_array_get (mb->pinfo, gpointer, i))
1588                                 count++;
1589                 }
1590                 table->rows += count;
1591                 alloc_table (table, table->rows);
1592                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1593                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1594                         MonoReflectionParamBuilder *pb;
1595                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1596                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1597                                 values [MONO_PARAM_SEQUENCE] = i;
1598                                 if (pb->name != NULL) {
1599                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1600                                 } else {
1601                                         values [MONO_PARAM_NAME] = 0;
1602                                 }
1603                                 values += MONO_PARAM_SIZE;
1604                                 if (pb->marshal_info) {
1605                                         mtable->rows++;
1606                                         alloc_table (mtable, mtable->rows);
1607                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1608                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1609                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1610                                 }
1611                                 pb->table_idx = table->next_idx++;
1612                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1613                                         guint32 field_type = 0;
1614                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1615                                         mtable->rows ++;
1616                                         alloc_table (mtable, mtable->rows);
1617                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1618                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1619                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1620                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1621                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1622                                 }
1623                         }
1624                 }
1625         }
1626 }
1627
1628 #ifndef DISABLE_REFLECTION_EMIT
1629 static void
1630 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1631 {
1632         MonoError error;
1633         MONO_REQ_GC_UNSAFE_MODE;
1634
1635         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1636
1637         rmb->ilgen = mb->ilgen;
1638         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, &error);
1639         mono_error_raise_exception (&error); /* FIXME don't raise here */
1640         rmb->parameters = mb->parameters;
1641         rmb->generic_params = mb->generic_params;
1642         rmb->generic_container = mb->generic_container;
1643         rmb->opt_types = NULL;
1644         rmb->pinfo = mb->pinfo;
1645         rmb->attrs = mb->attrs;
1646         rmb->iattrs = mb->iattrs;
1647         rmb->call_conv = mb->call_conv;
1648         rmb->code = mb->code;
1649         rmb->type = mb->type;
1650         rmb->name = mb->name;
1651         rmb->table_idx = &mb->table_idx;
1652         rmb->init_locals = mb->init_locals;
1653         rmb->skip_visibility = FALSE;
1654         rmb->return_modreq = mb->return_modreq;
1655         rmb->return_modopt = mb->return_modopt;
1656         rmb->param_modreq = mb->param_modreq;
1657         rmb->param_modopt = mb->param_modopt;
1658         rmb->permissions = mb->permissions;
1659         rmb->mhandle = mb->mhandle;
1660         rmb->nrefs = 0;
1661         rmb->refs = NULL;
1662
1663         if (mb->dll) {
1664                 rmb->charset = mb->charset;
1665                 rmb->extra_flags = mb->extra_flags;
1666                 rmb->native_cc = mb->native_cc;
1667                 rmb->dllentry = mb->dllentry;
1668                 rmb->dll = mb->dll;
1669         }
1670 }
1671
1672 static void
1673 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1674 {
1675         MONO_REQ_GC_UNSAFE_MODE;
1676
1677         MonoError error;
1678         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1679
1680         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1681
1682         rmb->ilgen = mb->ilgen;
1683         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1684         mono_error_raise_exception (&error); /* FIXME don't raise here */
1685         rmb->parameters = mb->parameters;
1686         rmb->generic_params = NULL;
1687         rmb->generic_container = NULL;
1688         rmb->opt_types = NULL;
1689         rmb->pinfo = mb->pinfo;
1690         rmb->attrs = mb->attrs;
1691         rmb->iattrs = mb->iattrs;
1692         rmb->call_conv = mb->call_conv;
1693         rmb->code = NULL;
1694         rmb->type = mb->type;
1695         rmb->name = mono_string_new (mono_domain_get (), name);
1696         rmb->table_idx = &mb->table_idx;
1697         rmb->init_locals = mb->init_locals;
1698         rmb->skip_visibility = FALSE;
1699         rmb->return_modreq = NULL;
1700         rmb->return_modopt = NULL;
1701         rmb->param_modreq = mb->param_modreq;
1702         rmb->param_modopt = mb->param_modopt;
1703         rmb->permissions = mb->permissions;
1704         rmb->mhandle = mb->mhandle;
1705         rmb->nrefs = 0;
1706         rmb->refs = NULL;
1707 }
1708
1709 static void
1710 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1711 {
1712         MONO_REQ_GC_UNSAFE_MODE;
1713
1714         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1715
1716         rmb->ilgen = mb->ilgen;
1717         rmb->rtype = mb->rtype;
1718         rmb->parameters = mb->parameters;
1719         rmb->generic_params = NULL;
1720         rmb->generic_container = NULL;
1721         rmb->opt_types = NULL;
1722         rmb->pinfo = NULL;
1723         rmb->attrs = mb->attrs;
1724         rmb->iattrs = 0;
1725         rmb->call_conv = mb->call_conv;
1726         rmb->code = NULL;
1727         rmb->type = (MonoObject *) mb->owner;
1728         rmb->name = mb->name;
1729         rmb->table_idx = NULL;
1730         rmb->init_locals = mb->init_locals;
1731         rmb->skip_visibility = mb->skip_visibility;
1732         rmb->return_modreq = NULL;
1733         rmb->return_modopt = NULL;
1734         rmb->param_modreq = NULL;
1735         rmb->param_modopt = NULL;
1736         rmb->permissions = NULL;
1737         rmb->mhandle = mb->mhandle;
1738         rmb->nrefs = 0;
1739         rmb->refs = NULL;
1740 }       
1741 #endif
1742
1743 static void
1744 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1745 {
1746         MONO_REQ_GC_UNSAFE_MODE;
1747
1748         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1749         MonoDynamicTable *table;
1750         guint32 *values;
1751         guint32 tok;
1752         MonoReflectionMethod *m;
1753         int i;
1754
1755         if (!mb->override_methods)
1756                 return;
1757
1758         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1759                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1760
1761                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1762                 table->rows ++;
1763                 alloc_table (table, table->rows);
1764                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1765                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1766                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1767
1768                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1769                 switch (mono_metadata_token_table (tok)) {
1770                 case MONO_TABLE_MEMBERREF:
1771                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1772                         break;
1773                 case MONO_TABLE_METHOD:
1774                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1775                         break;
1776                 default:
1777                         g_assert_not_reached ();
1778                 }
1779                 values [MONO_METHODIMPL_DECLARATION] = tok;
1780         }
1781 }
1782
1783 #ifndef DISABLE_REFLECTION_EMIT
1784 static void
1785 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1786 {
1787         MONO_REQ_GC_UNSAFE_MODE;
1788
1789         MonoDynamicTable *table;
1790         guint32 *values;
1791         ReflectionMethodBuilder rmb;
1792         int i;
1793
1794         reflection_methodbuilder_from_method_builder (&rmb, mb);
1795
1796         mono_image_basic_method (&rmb, assembly);
1797         mb->table_idx = *rmb.table_idx;
1798
1799         if (mb->dll) { /* It's a P/Invoke method */
1800                 guint32 moduleref;
1801                 /* map CharSet values to on-disk values */
1802                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1803                 int extra_flags = mb->extra_flags;
1804                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1805                 table->rows ++;
1806                 alloc_table (table, table->rows);
1807                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1808                 
1809                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1810                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1811                 if (mb->dllentry)
1812                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1813                 else
1814                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1815                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1816                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1817                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1818                         table->rows ++;
1819                         alloc_table (table, table->rows);
1820                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1821                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1822                 }
1823         }
1824
1825         if (mb->generic_params) {
1826                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1827                 table->rows += mono_array_length (mb->generic_params);
1828                 alloc_table (table, table->rows);
1829                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1830                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1831
1832                         mono_image_get_generic_param_info (
1833                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1834                 }
1835         }
1836
1837 }
1838
1839 static void
1840 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1841 {
1842         MONO_REQ_GC_UNSAFE_MODE;
1843
1844         ReflectionMethodBuilder rmb;
1845
1846         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1847
1848         mono_image_basic_method (&rmb, assembly);
1849         mb->table_idx = *rmb.table_idx;
1850 }
1851 #endif
1852
1853 static char*
1854 type_get_fully_qualified_name (MonoType *type)
1855 {
1856         MONO_REQ_GC_NEUTRAL_MODE;
1857
1858         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1859 }
1860
1861 static char*
1862 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1863 {
1864         MONO_REQ_GC_UNSAFE_MODE;
1865
1866         MonoClass *klass;
1867         MonoAssembly *ta;
1868
1869         klass = mono_class_from_mono_type (type);
1870         if (!klass) 
1871                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1872         ta = klass->image->assembly;
1873         if (assembly_is_dynamic (ta) || (ta == ass)) {
1874                 if (klass->generic_class || klass->generic_container)
1875                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1876                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1877                 else
1878                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1879         }
1880
1881         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1882 }
1883
1884 #ifndef DISABLE_REFLECTION_EMIT
1885 /*field_image is the image to which the eventual custom mods have been encoded against*/
1886 static guint32
1887 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1888 {
1889         MONO_REQ_GC_NEUTRAL_MODE;
1890
1891         SigBuffer buf;
1892         guint32 idx, i, token;
1893
1894         if (!assembly->save)
1895                 return 0;
1896
1897         sigbuffer_init (&buf, 32);
1898         
1899         sigbuffer_add_value (&buf, 0x06);
1900         /* encode custom attributes before the type */
1901         if (type->num_mods) {
1902                 for (i = 0; i < type->num_mods; ++i) {
1903                         if (field_image) {
1904                                 MonoError error;
1905                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1906                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1907
1908                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1909                         } else {
1910                                 token = type->modifiers [i].token;
1911                         }
1912
1913                         if (type->modifiers [i].required)
1914                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1915                         else
1916                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1917
1918                         sigbuffer_add_value (&buf, token);
1919                 }
1920         }
1921         encode_type (assembly, type, &buf);
1922         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1923         sigbuffer_free (&buf);
1924         return idx;
1925 }
1926 #endif
1927
1928 static guint32
1929 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1930 {
1931         MONO_REQ_GC_UNSAFE_MODE;
1932
1933         SigBuffer buf;
1934         guint32 idx;
1935         guint32 typespec = 0;
1936         MonoType *type;
1937         MonoClass *klass;
1938
1939         init_type_builder_generics (fb->type);
1940
1941         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1942         klass = mono_class_from_mono_type (type);
1943
1944         sigbuffer_init (&buf, 32);
1945         
1946         sigbuffer_add_value (&buf, 0x06);
1947         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1948         /* encode custom attributes before the type */
1949
1950         if (klass->generic_container)
1951                 typespec = create_typespec (assembly, type);
1952
1953         if (typespec) {
1954                 MonoGenericClass *gclass;
1955                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1956                 encode_generic_class (assembly, gclass, &buf);
1957         } else {
1958                 encode_type (assembly, type, &buf);
1959         }
1960         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961         sigbuffer_free (&buf);
1962         return idx;
1963 }
1964
1965 static guint32
1966 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1967 {
1968         MONO_REQ_GC_UNSAFE_MODE;
1969
1970         char blob_size [64];
1971         char *b = blob_size;
1972         char *box_val;
1973         char* buf;
1974         guint32 idx = 0, len = 0, dummy = 0;
1975
1976         buf = (char *)g_malloc (64);
1977         if (!val) {
1978                 *ret_type = MONO_TYPE_CLASS;
1979                 len = 4;
1980                 box_val = (char*)&dummy;
1981         } else {
1982                 box_val = ((char*)val) + sizeof (MonoObject);
1983                 *ret_type = val->vtable->klass->byval_arg.type;
1984         }
1985 handle_enum:
1986         switch (*ret_type) {
1987         case MONO_TYPE_BOOLEAN:
1988         case MONO_TYPE_U1:
1989         case MONO_TYPE_I1:
1990                 len = 1;
1991                 break;
1992         case MONO_TYPE_CHAR:
1993         case MONO_TYPE_U2:
1994         case MONO_TYPE_I2:
1995                 len = 2;
1996                 break;
1997         case MONO_TYPE_U4:
1998         case MONO_TYPE_I4:
1999         case MONO_TYPE_R4:
2000                 len = 4;
2001                 break;
2002         case MONO_TYPE_U8:
2003         case MONO_TYPE_I8:
2004                 len = 8;
2005                 break;
2006         case MONO_TYPE_R8:
2007                 len = 8;
2008                 break;
2009         case MONO_TYPE_VALUETYPE: {
2010                 MonoClass *klass = val->vtable->klass;
2011                 
2012                 if (klass->enumtype) {
2013                         *ret_type = mono_class_enum_basetype (klass)->type;
2014                         goto handle_enum;
2015                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2016                         len = 8;
2017                 } else 
2018                         g_error ("we can't encode valuetypes, we should have never reached this line");
2019                 break;
2020         }
2021         case MONO_TYPE_CLASS:
2022                 break;
2023         case MONO_TYPE_STRING: {
2024                 MonoString *str = (MonoString*)val;
2025                 /* there is no signature */
2026                 len = str->length * 2;
2027                 mono_metadata_encode_value (len, b, &b);
2028 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2029                 {
2030                         char *swapped = g_malloc (2 * mono_string_length (str));
2031                         const char *p = (const char*)mono_string_chars (str);
2032
2033                         swap_with_size (swapped, p, 2, mono_string_length (str));
2034                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2035                         g_free (swapped);
2036                 }
2037 #else
2038                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2039 #endif
2040
2041                 g_free (buf);
2042                 return idx;
2043         }
2044         case MONO_TYPE_GENERICINST:
2045                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2046                 goto handle_enum;
2047         default:
2048                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2049         }
2050
2051         /* there is no signature */
2052         mono_metadata_encode_value (len, b, &b);
2053 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2054         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2055         swap_with_size (blob_size, box_val, len, 1);
2056         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2057 #else
2058         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2059 #endif
2060
2061         g_free (buf);
2062         return idx;
2063 }
2064
2065 static guint32
2066 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2067 {
2068         MONO_REQ_GC_UNSAFE_MODE;
2069
2070         char *str;
2071         SigBuffer buf;
2072         guint32 idx, len;
2073
2074         sigbuffer_init (&buf, 32);
2075
2076         sigbuffer_add_value (&buf, minfo->type);
2077
2078         switch (minfo->type) {
2079         case MONO_NATIVE_BYVALTSTR:
2080         case MONO_NATIVE_BYVALARRAY:
2081                 sigbuffer_add_value (&buf, minfo->count);
2082                 break;
2083         case MONO_NATIVE_LPARRAY:
2084                 if (minfo->eltype || minfo->has_size) {
2085                         sigbuffer_add_value (&buf, minfo->eltype);
2086                         if (minfo->has_size) {
2087                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2088                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2089
2090                                 /* LAMESPEC: ElemMult is undocumented */
2091                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2092                         }
2093                 }
2094                 break;
2095         case MONO_NATIVE_SAFEARRAY:
2096                 if (minfo->eltype)
2097                         sigbuffer_add_value (&buf, minfo->eltype);
2098                 break;
2099         case MONO_NATIVE_CUSTOM:
2100                 if (minfo->guid) {
2101                         str = mono_string_to_utf8 (minfo->guid);
2102                         len = strlen (str);
2103                         sigbuffer_add_value (&buf, len);
2104                         sigbuffer_add_mem (&buf, str, len);
2105                         g_free (str);
2106                 } else {
2107                         sigbuffer_add_value (&buf, 0);
2108                 }
2109                 /* native type name */
2110                 sigbuffer_add_value (&buf, 0);
2111                 /* custom marshaler type name */
2112                 if (minfo->marshaltype || minfo->marshaltyperef) {
2113                         if (minfo->marshaltyperef)
2114                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2115                         else
2116                                 str = mono_string_to_utf8 (minfo->marshaltype);
2117                         len = strlen (str);
2118                         sigbuffer_add_value (&buf, len);
2119                         sigbuffer_add_mem (&buf, str, len);
2120                         g_free (str);
2121                 } else {
2122                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2123                         sigbuffer_add_value (&buf, 0);
2124                 }
2125                 if (minfo->mcookie) {
2126                         str = mono_string_to_utf8 (minfo->mcookie);
2127                         len = strlen (str);
2128                         sigbuffer_add_value (&buf, len);
2129                         sigbuffer_add_mem (&buf, str, len);
2130                         g_free (str);
2131                 } else {
2132                         sigbuffer_add_value (&buf, 0);
2133                 }
2134                 break;
2135         default:
2136                 break;
2137         }
2138         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2139         sigbuffer_free (&buf);
2140         return idx;
2141 }
2142
2143 static void
2144 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2145 {
2146         MONO_REQ_GC_UNSAFE_MODE;
2147
2148         MonoDynamicTable *table;
2149         guint32 *values;
2150
2151         /* maybe this fixup should be done in the C# code */
2152         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2153                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2154         table = &assembly->tables [MONO_TABLE_FIELD];
2155         fb->table_idx = table->next_idx ++;
2156         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2157         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2158         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2159         values [MONO_FIELD_FLAGS] = fb->attrs;
2160         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2161
2162         if (fb->offset != -1) {
2163                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2164                 table->rows ++;
2165                 alloc_table (table, table->rows);
2166                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2167                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2168                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2169         }
2170         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2171                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2172                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2173                 table->rows ++;
2174                 alloc_table (table, table->rows);
2175                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2176                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2177                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2178                 values [MONO_CONSTANT_TYPE] = field_type;
2179                 values [MONO_CONSTANT_PADDING] = 0;
2180         }
2181         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2182                 guint32 rva_idx;
2183                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2184                 table->rows ++;
2185                 alloc_table (table, table->rows);
2186                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2187                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2188                 /*
2189                  * We store it in the code section because it's simpler for now.
2190                  */
2191                 if (fb->rva_data) {
2192                         if (mono_array_length (fb->rva_data) >= 10)
2193                                 stream_data_align (&assembly->code);
2194                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2195                 } else
2196                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2197                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2198         }
2199         if (fb->marshal_info) {
2200                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2201                 table->rows ++;
2202                 alloc_table (table, table->rows);
2203                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2204                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2205                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2206         }
2207 }
2208
2209 static guint32
2210 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2211 {
2212         MONO_REQ_GC_UNSAFE_MODE;
2213
2214         SigBuffer buf;
2215         guint32 nparams = 0;
2216         MonoReflectionMethodBuilder *mb = fb->get_method;
2217         MonoReflectionMethodBuilder *smb = fb->set_method;
2218         guint32 idx, i;
2219
2220         if (mb && mb->parameters)
2221                 nparams = mono_array_length (mb->parameters);
2222         if (!mb && smb && smb->parameters)
2223                 nparams = mono_array_length (smb->parameters) - 1;
2224         sigbuffer_init (&buf, 32);
2225         if (fb->call_conv & 0x20)
2226                 sigbuffer_add_byte (&buf, 0x28);
2227         else
2228                 sigbuffer_add_byte (&buf, 0x08);
2229         sigbuffer_add_value (&buf, nparams);
2230         if (mb) {
2231                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2232                 for (i = 0; i < nparams; ++i) {
2233                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2234                         encode_reflection_type (assembly, pt, &buf);
2235                 }
2236         } else if (smb && smb->parameters) {
2237                 /* the property type is the last param */
2238                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2239                 for (i = 0; i < nparams; ++i) {
2240                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2241                         encode_reflection_type (assembly, pt, &buf);
2242                 }
2243         } else {
2244                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2245         }
2246
2247         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2248         sigbuffer_free (&buf);
2249         return idx;
2250 }
2251
2252 static void
2253 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2254 {
2255         MONO_REQ_GC_UNSAFE_MODE;
2256
2257         MonoDynamicTable *table;
2258         guint32 *values;
2259         guint num_methods = 0;
2260         guint32 semaidx;
2261
2262         /* 
2263          * we need to set things in the following tables:
2264          * PROPERTYMAP (info already filled in _get_type_info ())
2265          * PROPERTY    (rows already preallocated in _get_type_info ())
2266          * METHOD      (method info already done with the generic method code)
2267          * METHODSEMANTICS
2268          * CONSTANT
2269          */
2270         table = &assembly->tables [MONO_TABLE_PROPERTY];
2271         pb->table_idx = table->next_idx ++;
2272         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2273         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2274         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2275         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2276
2277         /* FIXME: we still don't handle 'other' methods */
2278         if (pb->get_method) num_methods ++;
2279         if (pb->set_method) num_methods ++;
2280
2281         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2282         table->rows += num_methods;
2283         alloc_table (table, table->rows);
2284
2285         if (pb->get_method) {
2286                 semaidx = table->next_idx ++;
2287                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2289                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2290                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2291         }
2292         if (pb->set_method) {
2293                 semaidx = table->next_idx ++;
2294                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2295                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2296                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2297                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2298         }
2299         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2300                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2301                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2302                 table->rows ++;
2303                 alloc_table (table, table->rows);
2304                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2305                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2306                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2307                 values [MONO_CONSTANT_TYPE] = field_type;
2308                 values [MONO_CONSTANT_PADDING] = 0;
2309         }
2310 }
2311
2312 static void
2313 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2314 {
2315         MONO_REQ_GC_UNSAFE_MODE;
2316
2317         MonoDynamicTable *table;
2318         guint32 *values;
2319         guint num_methods = 0;
2320         guint32 semaidx;
2321
2322         /* 
2323          * we need to set things in the following tables:
2324          * EVENTMAP (info already filled in _get_type_info ())
2325          * EVENT    (rows already preallocated in _get_type_info ())
2326          * METHOD      (method info already done with the generic method code)
2327          * METHODSEMANTICS
2328          */
2329         table = &assembly->tables [MONO_TABLE_EVENT];
2330         eb->table_idx = table->next_idx ++;
2331         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2332         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2333         values [MONO_EVENT_FLAGS] = eb->attrs;
2334         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2335
2336         /*
2337          * FIXME: we still don't handle 'other' methods 
2338          */
2339         if (eb->add_method) num_methods ++;
2340         if (eb->remove_method) num_methods ++;
2341         if (eb->raise_method) num_methods ++;
2342
2343         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2344         table->rows += num_methods;
2345         alloc_table (table, table->rows);
2346
2347         if (eb->add_method) {
2348                 semaidx = table->next_idx ++;
2349                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2351                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2352                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2353         }
2354         if (eb->remove_method) {
2355                 semaidx = table->next_idx ++;
2356                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2358                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2359                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2360         }
2361         if (eb->raise_method) {
2362                 semaidx = table->next_idx ++;
2363                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2364                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2365                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2366                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2367         }
2368 }
2369
2370 static void
2371 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2372 {
2373         MONO_REQ_GC_UNSAFE_MODE;
2374
2375         MonoDynamicTable *table;
2376         guint32 num_constraints, i;
2377         guint32 *values;
2378         guint32 table_idx;
2379
2380         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2381         num_constraints = gparam->iface_constraints ?
2382                 mono_array_length (gparam->iface_constraints) : 0;
2383         table->rows += num_constraints;
2384         if (gparam->base_type)
2385                 table->rows++;
2386         alloc_table (table, table->rows);
2387
2388         if (gparam->base_type) {
2389                 table_idx = table->next_idx ++;
2390                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2391
2392                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2393                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2394                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2395         }
2396
2397         for (i = 0; i < num_constraints; i++) {
2398                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2399                         gparam->iface_constraints, gpointer, i);
2400
2401                 table_idx = table->next_idx ++;
2402                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2403
2404                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2405                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2406                         assembly, mono_reflection_type_get_handle (constraint));
2407         }
2408 }
2409
2410 static void
2411 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2412 {
2413         MONO_REQ_GC_UNSAFE_MODE;
2414
2415         GenericParamTableEntry *entry;
2416
2417         /*
2418          * The GenericParam table must be sorted according to the `owner' field.
2419          * We need to do this sorting prior to writing the GenericParamConstraint
2420          * table, since we have to use the final GenericParam table indices there
2421          * and they must also be sorted.
2422          */
2423
2424         entry = g_new0 (GenericParamTableEntry, 1);
2425         entry->owner = owner;
2426         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2427         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2428         entry->gparam = gparam;
2429         
2430         g_ptr_array_add (assembly->gen_params, entry);
2431 }
2432
2433 static void
2434 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2435 {
2436         MONO_REQ_GC_UNSAFE_MODE;
2437
2438         MonoDynamicTable *table;
2439         MonoGenericParam *param;
2440         guint32 *values;
2441         guint32 table_idx;
2442
2443         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2444         table_idx = table->next_idx ++;
2445         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2446
2447         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2448
2449         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2450         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2451         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2452         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2453
2454         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2455
2456         encode_constraints (entry->gparam, table_idx, assembly);
2457 }
2458
2459 static guint32
2460 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2461 {
2462         MONO_REQ_GC_UNSAFE_MODE;
2463
2464         MonoDynamicTable *table;
2465         guint32 token;
2466         guint32 *values;
2467         guint32 cols [MONO_ASSEMBLY_SIZE];
2468         const char *pubkey;
2469         guint32 publen;
2470
2471         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2472                 return token;
2473
2474         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2475                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2476                 token = table->next_idx ++;
2477                 table->rows ++;
2478                 alloc_table (table, table->rows);
2479                 values = table->values + token * MONO_MODULEREF_SIZE;
2480                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2481
2482                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2483                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2484                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2485
2486                 return token;
2487         }
2488         
2489         if (assembly_is_dynamic (image->assembly))
2490                 /* FIXME: */
2491                 memset (cols, 0, sizeof (cols));
2492         else {
2493                 /* image->assembly->image is the manifest module */
2494                 image = image->assembly->image;
2495                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2496         }
2497
2498         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2499         token = table->next_idx ++;
2500         table->rows ++;
2501         alloc_table (table, table->rows);
2502         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2503         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2504         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2505         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2506         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2507         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2508         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2509         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2510         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2511
2512         if (strcmp ("", image->assembly->aname.culture)) {
2513                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2514                                 image->assembly->aname.culture);
2515         }
2516
2517         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2518                 guchar pubtoken [9];
2519                 pubtoken [0] = 8;
2520                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2521                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2522         } else {
2523                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2524         }
2525         token <<= MONO_RESOLUTION_SCOPE_BITS;
2526         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2527         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2528         return token;
2529 }
2530
2531 static guint32
2532 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2533 {
2534         MONO_REQ_GC_NEUTRAL_MODE;
2535
2536         MonoDynamicTable *table;
2537         guint32 *values;
2538         guint32 token;
2539         SigBuffer buf;
2540
2541         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2542                 return token;
2543
2544         sigbuffer_init (&buf, 32);
2545         switch (type->type) {
2546         case MONO_TYPE_FNPTR:
2547         case MONO_TYPE_PTR:
2548         case MONO_TYPE_SZARRAY:
2549         case MONO_TYPE_ARRAY:
2550         case MONO_TYPE_VAR:
2551         case MONO_TYPE_MVAR:
2552         case MONO_TYPE_GENERICINST:
2553                 encode_type (assembly, type, &buf);
2554                 break;
2555         case MONO_TYPE_CLASS:
2556         case MONO_TYPE_VALUETYPE: {
2557                 MonoClass *k = mono_class_from_mono_type (type);
2558                 if (!k || !k->generic_container) {
2559                         sigbuffer_free (&buf);
2560                         return 0;
2561                 }
2562                 encode_type (assembly, type, &buf);
2563                 break;
2564         }
2565         default:
2566                 sigbuffer_free (&buf);
2567                 return 0;
2568         }
2569
2570         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571         if (assembly->save) {
2572                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2573                 alloc_table (table, table->rows + 1);
2574                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575                 values [MONO_TYPESPEC_SIGNATURE] = token;
2576         }
2577         sigbuffer_free (&buf);
2578
2579         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2581         table->next_idx ++;
2582         return token;
2583 }
2584
2585 static guint32
2586 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2587 {
2588         MONO_REQ_GC_UNSAFE_MODE;
2589
2590         MonoDynamicTable *table;
2591         guint32 *values;
2592         guint32 token, scope, enclosing;
2593         MonoClass *klass;
2594
2595         /* if the type requires a typespec, we must try that first*/
2596         if (try_typespec && (token = create_typespec (assembly, type)))
2597                 return token;
2598         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2599         if (token)
2600                 return token;
2601         klass = mono_class_from_mono_type (type);
2602         if (!klass)
2603                 klass = mono_class_from_mono_type (type);
2604
2605         /*
2606          * If it's in the same module and not a generic type parameter:
2607          */
2608         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2609                         (type->type != MONO_TYPE_MVAR)) {
2610                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2611                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2612                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2613                 return token;
2614         }
2615
2616         if (klass->nested_in) {
2617                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2618                 /* get the typeref idx of the enclosing type */
2619                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2620                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2621         } else {
2622                 scope = resolution_scope_from_image (assembly, klass->image);
2623         }
2624         table = &assembly->tables [MONO_TABLE_TYPEREF];
2625         if (assembly->save) {
2626                 alloc_table (table, table->rows + 1);
2627                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2628                 values [MONO_TYPEREF_SCOPE] = scope;
2629                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2630                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2631         }
2632         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2633         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2634         table->next_idx ++;
2635         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2636         return token;
2637 }
2638
2639 /*
2640  * Despite the name, we handle also TypeSpec (with the above helper).
2641  */
2642 static guint32
2643 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2644 {
2645         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2646 }
2647
2648 #ifndef DISABLE_REFLECTION_EMIT
2649 static guint32
2650 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2651 {
2652         MONO_REQ_GC_NEUTRAL_MODE;
2653
2654         MonoDynamicTable *table;
2655         guint32 *values;
2656         guint32 token, pclass;
2657
2658         switch (parent & MONO_TYPEDEFORREF_MASK) {
2659         case MONO_TYPEDEFORREF_TYPEREF:
2660                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2661                 break;
2662         case MONO_TYPEDEFORREF_TYPESPEC:
2663                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2664                 break;
2665         case MONO_TYPEDEFORREF_TYPEDEF:
2666                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2667                 break;
2668         default:
2669                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2670                 return 0;
2671         }
2672         /* extract the index */
2673         parent >>= MONO_TYPEDEFORREF_BITS;
2674
2675         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2676
2677         if (assembly->save) {
2678                 alloc_table (table, table->rows + 1);
2679                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2680                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2681                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2682                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2683         }
2684
2685         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2686         table->next_idx ++;
2687
2688         return token;
2689 }
2690
2691 /*
2692  * Insert a memberef row into the metadata: the token that point to the memberref
2693  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2694  * mono_image_get_fieldref_token()).
2695  * The sig param is an index to an already built signature.
2696  */
2697 static guint32
2698 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2699 {
2700         MONO_REQ_GC_NEUTRAL_MODE;
2701
2702         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2703         return mono_image_add_memberef_row (assembly, parent, name, sig);
2704 }
2705
2706
2707 static guint32
2708 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2709 {
2710         MONO_REQ_GC_NEUTRAL_MODE;
2711
2712         guint32 token;
2713         MonoMethodSignature *sig;
2714         
2715         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2716
2717         if (create_typespec) {
2718                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2719                 if (token)
2720                         return token;
2721         } 
2722
2723         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2724         if (token && !create_typespec)
2725                 return token;
2726
2727         g_assert (!method->is_inflated);
2728         if (!token) {
2729                 /*
2730                  * A methodref signature can't contain an unmanaged calling convention.
2731                  */
2732                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2733                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2734                         sig->call_convention = MONO_CALL_DEFAULT;
2735                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2736                         method->name,  method_encode_signature (assembly, sig));
2737                 g_free (sig);
2738                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2739         }
2740
2741         if (create_typespec) {
2742                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2743                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2744                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2745
2746                 if (assembly->save) {
2747                         guint32 *values;
2748
2749                         alloc_table (table, table->rows + 1);
2750                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2751                         values [MONO_METHODSPEC_METHOD] = token;
2752                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2753                 }
2754
2755                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2756                 table->next_idx ++;
2757                 /*methodspec and memberef tokens are diferent, */
2758                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2759                 return token;
2760         }
2761         return token;
2762 }
2763
2764 static guint32
2765 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2766 {
2767         guint32 token, parent, sig;
2768         ReflectionMethodBuilder rmb;
2769         char *name;
2770         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2771         
2772         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2773         if (token)
2774                 return token;
2775
2776         name = mono_string_to_utf8 (method->name);
2777         reflection_methodbuilder_from_method_builder (&rmb, method);
2778
2779         /*
2780          * A methodref signature can't contain an unmanaged calling convention.
2781          * Since some flags are encoded as part of call_conv, we need to check against it.
2782         */
2783         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2784                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2785
2786         sig = method_builder_encode_signature (assembly, &rmb);
2787
2788         if (tb->generic_params)
2789                 parent = create_generic_typespec (assembly, tb);
2790         else
2791                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2792
2793         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2794
2795         g_free (name);
2796         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2797         return token;
2798 }
2799
2800 static guint32
2801 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2802                                      const gchar *name, guint32 sig)
2803 {
2804         MonoDynamicTable *table;
2805         guint32 token;
2806         guint32 *values;
2807         
2808         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2809
2810         if (assembly->save) {
2811                 alloc_table (table, table->rows + 1);
2812                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2813                 values [MONO_MEMBERREF_CLASS] = original;
2814                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2815                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2816         }
2817
2818         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2819         table->next_idx ++;
2820
2821         return token;
2822 }
2823
2824 static guint32
2825 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2826 {
2827         SigBuffer buf;
2828         int i;
2829         guint32 nparams = mono_array_length (mb->generic_params);
2830         guint32 idx;
2831
2832         if (!assembly->save)
2833                 return 0;
2834
2835         sigbuffer_init (&buf, 32);
2836
2837         sigbuffer_add_value (&buf, 0xa);
2838         sigbuffer_add_value (&buf, nparams);
2839
2840         for (i = 0; i < nparams; i++) {
2841                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2842                 sigbuffer_add_value (&buf, i);
2843         }
2844
2845         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2846         sigbuffer_free (&buf);
2847         return idx;
2848 }
2849
2850 static guint32
2851 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2852 {
2853         MonoDynamicTable *table;
2854         guint32 *values;
2855         guint32 token, mtoken = 0;
2856
2857         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2858         if (token)
2859                 return token;
2860
2861         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2862
2863         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2864         switch (mono_metadata_token_table (mtoken)) {
2865         case MONO_TABLE_MEMBERREF:
2866                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2867                 break;
2868         case MONO_TABLE_METHOD:
2869                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2870                 break;
2871         default:
2872                 g_assert_not_reached ();
2873         }
2874
2875         if (assembly->save) {
2876                 alloc_table (table, table->rows + 1);
2877                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2878                 values [MONO_METHODSPEC_METHOD] = mtoken;
2879                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2880         }
2881
2882         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2883         table->next_idx ++;
2884
2885         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2886         return token;
2887 }
2888
2889 static guint32
2890 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2891 {
2892         guint32 token;
2893
2894         if (mb->generic_params && create_methodspec) 
2895                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2896
2897         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2898         if (token)
2899                 return token;
2900
2901         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2902         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2903         return token;
2904 }
2905
2906 static guint32
2907 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2908 {
2909         guint32 token, parent, sig;
2910         ReflectionMethodBuilder rmb;
2911         char *name;
2912         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2913         
2914         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2915         if (token)
2916                 return token;
2917
2918         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2919
2920         if (tb->generic_params)
2921                 parent = create_generic_typespec (assembly, tb);
2922         else
2923                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2924         
2925         name = mono_string_to_utf8 (rmb.name);
2926         sig = method_builder_encode_signature (assembly, &rmb);
2927
2928         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2929
2930         g_free (name);
2931         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2932         return token;
2933 }
2934 #endif
2935
2936 static gboolean
2937 is_field_on_inst (MonoClassField *field)
2938 {
2939         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2940 }
2941
2942 /*
2943  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2944  */
2945 static MonoType*
2946 get_field_on_inst_generic_type (MonoClassField *field)
2947 {
2948         MonoClass *klass, *gtd;
2949         MonoDynamicGenericClass *dgclass;
2950         int field_index;
2951
2952         g_assert (is_field_on_inst (field));
2953
2954         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2955
2956         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2957                 field_index = field - dgclass->fields;
2958                 return dgclass->field_generic_types [field_index];              
2959         }
2960
2961         klass = field->parent;
2962         gtd = klass->generic_class->container_class;
2963
2964         if (field >= klass->fields && field - klass->fields < klass->field.count) {
2965                 field_index = field - klass->fields;
2966                 return gtd->fields [field_index].type;
2967         }
2968
2969         g_assert_not_reached ();
2970         return 0;
2971 }
2972
2973 #ifndef DISABLE_REFLECTION_EMIT
2974 static guint32
2975 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2976 {
2977         MonoType *type;
2978         guint32 token;
2979
2980         g_assert (field);
2981         g_assert (field->parent);
2982
2983         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2984         if (token)
2985                 return token;
2986
2987         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2988                 int index = field - field->parent->fields;
2989                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2990         } else {
2991                 if (is_field_on_inst (field))
2992                         type = get_field_on_inst_generic_type (field);
2993                 else
2994                         type = mono_field_get_type (field);
2995         }
2996         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2997                                                                                         mono_field_get_name (field),
2998                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2999         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3000         return token;
3001 }
3002
3003 static guint32
3004 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3005 {
3006         guint32 token;
3007         MonoClass *klass;
3008         MonoGenericClass *gclass;
3009         MonoType *type;
3010         char *name;
3011
3012         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3013         if (token)
3014                 return token;
3015         if (is_sre_field_builder (mono_object_class (f->fb))) {
3016                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3017                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3018                 klass = mono_class_from_mono_type (type);
3019                 gclass = type->data.generic_class;
3020                 g_assert (gclass->is_dynamic);
3021
3022                 name = mono_string_to_utf8 (fb->name);
3023                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3024                                                                                                 field_encode_signature (assembly, fb));
3025                 g_free (name);          
3026         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3027                 guint32 sig;
3028                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3029
3030                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3031                 klass = mono_class_from_mono_type (type);
3032
3033                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3034                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3035         } else {
3036                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3037                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3038         }
3039
3040         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3041         return token;
3042 }
3043
3044 static guint32
3045 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3046 {
3047         guint32 sig, token;
3048         MonoClass *klass;
3049         MonoGenericClass *gclass;
3050         MonoType *type;
3051
3052         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3053
3054         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3055         if (token)
3056                 return token;
3057
3058         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3059                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3060                 ReflectionMethodBuilder rmb;
3061                 char *name;
3062
3063                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3064                 klass = mono_class_from_mono_type (type);
3065
3066                 gclass = type->data.generic_class;
3067                 g_assert (gclass->is_dynamic);
3068
3069                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3070
3071                 name = mono_string_to_utf8 (rmb.name);
3072
3073                 sig = method_builder_encode_signature (assembly, &rmb);
3074
3075                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3076                 g_free (name);
3077         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3078                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3079
3080                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3081                 klass = mono_class_from_mono_type (type);
3082
3083                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3084                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3085         } else {
3086                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3087                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3088         }
3089
3090
3091         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3092         return token;
3093 }
3094
3095 static MonoMethod*
3096 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3097 {
3098         MonoError error;
3099         MonoClass *klass;
3100         MonoGenericContext tmp_context;
3101         MonoType **type_argv;
3102         MonoGenericInst *ginst;
3103         MonoMethod *method, *inflated;
3104         int count, i;
3105
3106         init_type_builder_generics ((MonoObject*)m->inst);
3107
3108         method = inflate_method (m->inst, (MonoObject*)m->mb);
3109
3110         klass = method->klass;
3111
3112         if (m->method_args == NULL)
3113                 return method;
3114
3115         if (method->is_inflated)
3116                 method = ((MonoMethodInflated *) method)->declaring;
3117
3118         count = mono_array_length (m->method_args);
3119
3120         type_argv = g_new0 (MonoType *, count);
3121         for (i = 0; i < count; i++) {
3122                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3123                 type_argv [i] = mono_reflection_type_get_handle (garg);
3124         }
3125         ginst = mono_metadata_get_generic_inst (count, type_argv);
3126         g_free (type_argv);
3127
3128         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3129         tmp_context.method_inst = ginst;
3130
3131         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3132         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3133         return inflated;
3134 }
3135
3136 static guint32
3137 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3138 {
3139         guint32 sig, token = 0;
3140         MonoType *type;
3141         MonoClass *klass;
3142
3143         if (m->method_args) {
3144                 MonoMethod *inflated;
3145
3146                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3147                 if (create_methodspec)
3148                         token = mono_image_get_methodspec_token (assembly, inflated);
3149                 else
3150                         token = mono_image_get_inflated_method_token (assembly, inflated);
3151                 return token;
3152         }
3153
3154         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3155         if (token)
3156                 return token;
3157
3158         if (is_sre_method_builder (mono_object_class (m->mb))) {
3159                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3160                 MonoGenericClass *gclass;
3161                 ReflectionMethodBuilder rmb;
3162                 char *name;
3163
3164                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3165                 klass = mono_class_from_mono_type (type);
3166                 gclass = type->data.generic_class;
3167                 g_assert (gclass->is_dynamic);
3168
3169                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3170
3171                 name = mono_string_to_utf8 (rmb.name);
3172
3173                 sig = method_builder_encode_signature (assembly, &rmb);
3174
3175                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3176                 g_free (name);          
3177         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3178                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3179
3180                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3181                 klass = mono_class_from_mono_type (type);
3182
3183                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3184                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3185         } else {
3186                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3187                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3188         }
3189
3190         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3191         return token;
3192 }
3193
3194 static guint32
3195 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3196 {
3197         SigBuffer buf;
3198         int i;
3199         guint32 nparams = context->method_inst->type_argc;
3200         guint32 idx;
3201
3202         if (!assembly->save)
3203                 return 0;
3204
3205         sigbuffer_init (&buf, 32);
3206         /*
3207          * FIXME: vararg, explicit_this, differenc call_conv values...
3208          */
3209         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3210         sigbuffer_add_value (&buf, nparams);
3211
3212         for (i = 0; i < nparams; i++)
3213                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3214
3215         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3216         sigbuffer_free (&buf);
3217         return idx;
3218 }
3219
3220 static guint32
3221 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3222 {
3223         MonoDynamicTable *table;
3224         guint32 *values;
3225         guint32 token, mtoken = 0, sig;
3226         MonoMethodInflated *imethod;
3227         MonoMethod *declaring;
3228
3229         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3230
3231         g_assert (method->is_inflated);
3232         imethod = (MonoMethodInflated *) method;
3233         declaring = imethod->declaring;
3234
3235         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3236         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3237
3238         if (!mono_method_signature (declaring)->generic_param_count)
3239                 return mtoken;
3240
3241         switch (mono_metadata_token_table (mtoken)) {
3242         case MONO_TABLE_MEMBERREF:
3243                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3244                 break;
3245         case MONO_TABLE_METHOD:
3246                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3247                 break;
3248         default:
3249                 g_assert_not_reached ();
3250         }
3251
3252         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3253
3254         if (assembly->save) {
3255                 alloc_table (table, table->rows + 1);
3256                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3257                 values [MONO_METHODSPEC_METHOD] = mtoken;
3258                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3259         }
3260
3261         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3262         table->next_idx ++;
3263
3264         return token;
3265 }
3266
3267 static guint32
3268 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3269 {
3270         MonoMethodInflated *imethod;
3271         guint32 token;
3272         
3273         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3274         if (token)
3275                 return token;
3276
3277         g_assert (method->is_inflated);
3278         imethod = (MonoMethodInflated *) method;
3279
3280         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3281                 token = method_encode_methodspec (assembly, method);
3282         } else {
3283                 guint32 sig = method_encode_signature (
3284                         assembly, mono_method_signature (imethod->declaring));
3285                 token = mono_image_get_memberref_token (
3286                         assembly, &method->klass->byval_arg, method->name, sig);
3287         }
3288
3289         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3290         return token;
3291 }
3292
3293 static guint32
3294 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3295 {
3296         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3297         guint32 sig, token;
3298
3299         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3300         token = mono_image_get_memberref_token (
3301                 assembly, &m->klass->byval_arg, m->name, sig);
3302
3303         return token;
3304 }
3305
3306 static guint32
3307 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3308 {
3309         MonoDynamicTable *table;
3310         MonoClass *klass;
3311         MonoType *type;
3312         guint32 *values;
3313         guint32 token;
3314         SigBuffer buf;
3315         int count, i;
3316
3317         /*
3318          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3319          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3320          * Because of this, we must not insert it into the `typeref' hash table.
3321          */
3322         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3323         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3324         if (token)
3325                 return token;
3326
3327         sigbuffer_init (&buf, 32);
3328
3329         g_assert (tb->generic_params);
3330         klass = mono_class_from_mono_type (type);
3331
3332         if (tb->generic_container)
3333                 mono_reflection_create_generic_class (tb);
3334
3335         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3336         g_assert (klass->generic_container);
3337         sigbuffer_add_value (&buf, klass->byval_arg.type);
3338         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3339
3340         count = mono_array_length (tb->generic_params);
3341         sigbuffer_add_value (&buf, count);
3342         for (i = 0; i < count; i++) {
3343                 MonoReflectionGenericParam *gparam;
3344
3345                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3346
3347                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3348         }
3349
3350         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3351
3352         if (assembly->save) {
3353                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3354                 alloc_table (table, table->rows + 1);
3355                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3356                 values [MONO_TYPESPEC_SIGNATURE] = token;
3357         }
3358         sigbuffer_free (&buf);
3359
3360         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3361         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3362         table->next_idx ++;
3363         return token;
3364 }
3365
3366 /*
3367  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3368  */
3369 static MonoType*
3370 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3371 {
3372         int i, count, len, pos;
3373         MonoType *t;
3374
3375         count = 0;
3376         if (modreq)
3377                 count += mono_array_length (modreq);
3378         if (modopt)
3379                 count += mono_array_length (modopt);
3380
3381         if (count == 0)
3382                 return mono_metadata_type_dup (NULL, type);
3383
3384         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3385         t = (MonoType *)g_malloc (len);
3386         memcpy (t, type, MONO_SIZEOF_TYPE);
3387
3388         t->num_mods = count;
3389         pos = 0;
3390         if (modreq) {
3391                 for (i = 0; i < mono_array_length (modreq); ++i) {
3392                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3393                         t->modifiers [pos].required = 1;
3394                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3395                         pos ++;
3396                 }
3397         }
3398         if (modopt) {
3399                 for (i = 0; i < mono_array_length (modopt); ++i) {
3400                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3401                         t->modifiers [pos].required = 0;
3402                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3403                         pos ++;
3404                 }
3405         }
3406
3407         return t;
3408 }
3409
3410 static void
3411 init_type_builder_generics (MonoObject *type)
3412 {
3413         MonoReflectionTypeBuilder *tb;
3414
3415         if (!is_sre_type_builder(mono_object_class (type)))
3416                 return;
3417         tb = (MonoReflectionTypeBuilder *)type;
3418
3419         if (tb && tb->generic_container)
3420                 mono_reflection_create_generic_class (tb);
3421 }
3422
3423 static guint32
3424 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3425 {
3426         MonoDynamicTable *table;
3427         MonoType *custom = NULL, *type;
3428         guint32 *values;
3429         guint32 token, pclass, parent, sig;
3430         gchar *name;
3431
3432         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3433         if (token)
3434                 return token;
3435
3436         /* FIXME: is this call necessary? */
3437         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3438         name = mono_string_to_utf8 (fb->name);
3439
3440         /*FIXME this is one more layer of ugliness due how types are created.*/
3441         init_type_builder_generics (fb->type);
3442
3443         /* fb->type does not include the custom modifiers */
3444         /* FIXME: We should do this in one place when a fieldbuilder is created */
3445         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3446         if (fb->modreq || fb->modopt)
3447                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3448
3449         sig = fieldref_encode_signature (assembly, NULL, type);
3450         g_free (custom);
3451
3452         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3453         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3454         
3455         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3456         parent >>= MONO_TYPEDEFORREF_BITS;
3457
3458         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3459
3460         if (assembly->save) {
3461                 alloc_table (table, table->rows + 1);
3462                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3463                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3464                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3465                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3466         }
3467
3468         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3469         table->next_idx ++;
3470         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3471         g_free (name);
3472         return token;
3473 }
3474
3475 static guint32
3476 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3477 {
3478         SigBuffer buf;
3479         guint32 nargs;
3480         guint32 i, idx;
3481
3482         if (!assembly->save)
3483                 return 0;
3484
3485         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3486         g_assert (helper->type == 2);
3487
3488         if (helper->arguments)
3489                 nargs = mono_array_length (helper->arguments);
3490         else
3491                 nargs = 0;
3492
3493         sigbuffer_init (&buf, 32);
3494
3495         /* Encode calling convention */
3496         /* Change Any to Standard */
3497         if ((helper->call_conv & 0x03) == 0x03)
3498                 helper->call_conv = 0x01;
3499         /* explicit_this implies has_this */
3500         if (helper->call_conv & 0x40)
3501                 helper->call_conv &= 0x20;
3502
3503         if (helper->call_conv == 0) { /* Unmanaged */
3504                 idx = helper->unmanaged_call_conv - 1;
3505         } else {
3506                 /* Managed */
3507                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3508                 if (helper->call_conv & 0x02) /* varargs */
3509                         idx += 0x05;
3510         }
3511
3512         sigbuffer_add_byte (&buf, idx);
3513         sigbuffer_add_value (&buf, nargs);
3514         encode_reflection_type (assembly, helper->return_type, &buf);
3515         for (i = 0; i < nargs; ++i) {
3516                 MonoArray *modreqs = NULL;
3517                 MonoArray *modopts = NULL;
3518                 MonoReflectionType *pt;
3519
3520                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3521                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3522                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3523                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3524
3525                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3526                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3527                 encode_reflection_type (assembly, pt, &buf);
3528         }
3529         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3530         sigbuffer_free (&buf);
3531
3532         return idx;
3533 }
3534
3535 static guint32 
3536 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3537 {
3538         guint32 idx;
3539         MonoDynamicTable *table;
3540         guint32 *values;
3541
3542         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3543         idx = table->next_idx ++;
3544         table->rows ++;
3545         alloc_table (table, table->rows);
3546         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3547
3548         values [MONO_STAND_ALONE_SIGNATURE] =
3549                 mono_reflection_encode_sighelper (assembly, helper);
3550
3551         return idx;
3552 }
3553
3554 static int
3555 reflection_cc_to_file (int call_conv) {
3556         switch (call_conv & 0x3) {
3557         case 0:
3558         case 1: return MONO_CALL_DEFAULT;
3559         case 2: return MONO_CALL_VARARG;
3560         default:
3561                 g_assert_not_reached ();
3562         }
3563         return 0;
3564 }
3565 #endif /* !DISABLE_REFLECTION_EMIT */
3566
3567 typedef struct {
3568         MonoType *parent;
3569         MonoMethodSignature *sig;
3570         char *name;
3571         guint32 token;
3572 } ArrayMethod;
3573
3574 #ifndef DISABLE_REFLECTION_EMIT
3575 static guint32
3576 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3577 {
3578         guint32 nparams, i;
3579         GList *tmp;
3580         char *name;
3581         MonoMethodSignature *sig;
3582         ArrayMethod *am;
3583         MonoType *mtype;
3584
3585         name = mono_string_to_utf8 (m->name);
3586         nparams = mono_array_length (m->parameters);
3587         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3588         sig->hasthis = 1;
3589         sig->sentinelpos = -1;
3590         sig->call_convention = reflection_cc_to_file (m->call_conv);
3591         sig->param_count = nparams;
3592         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3593         mtype = mono_reflection_type_get_handle (m->parent);
3594         for (i = 0; i < nparams; ++i)
3595                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3596
3597         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3598                 am = (ArrayMethod *)tmp->data;
3599                 if (strcmp (name, am->name) == 0 && 
3600                                 mono_metadata_type_equal (am->parent, mtype) &&
3601                                 mono_metadata_signature_equal (am->sig, sig)) {
3602                         g_free (name);
3603                         g_free (sig);
3604                         m->table_idx = am->token & 0xffffff;
3605                         return am->token;
3606                 }
3607         }
3608         am = g_new0 (ArrayMethod, 1);
3609         am->name = name;
3610         am->sig = sig;
3611         am->parent = mtype;
3612         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3613                 method_encode_signature (assembly, sig));
3614         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3615         m->table_idx = am->token & 0xffffff;
3616         return am->token;
3617 }
3618
3619 /*
3620  * Insert into the metadata tables all the info about the TypeBuilder tb.
3621  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3622  */
3623 static void
3624 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3625 {
3626         MonoDynamicTable *table;
3627         guint *values;
3628         int i, is_object = 0, is_system = 0;
3629         char *n;
3630
3631         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3632         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3633         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3634         n = mono_string_to_utf8 (tb->name);
3635         if (strcmp (n, "Object") == 0)
3636                 is_object++;
3637         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3638         g_free (n);
3639         n = mono_string_to_utf8 (tb->nspace);
3640         if (strcmp (n, "System") == 0)
3641                 is_system++;
3642         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3643         g_free (n);
3644         if (tb->parent && !(is_system && is_object) && 
3645                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3646                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3647         } else {
3648                 values [MONO_TYPEDEF_EXTENDS] = 0;
3649         }
3650         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3651         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3652
3653         /*
3654          * if we have explicitlayout or sequentiallayouts, output data in the
3655          * ClassLayout table.
3656          */
3657         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3658                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3659                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3660                 table->rows++;
3661                 alloc_table (table, table->rows);
3662                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3663                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3664                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3665                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3666         }
3667
3668         /* handle interfaces */
3669         if (tb->interfaces) {
3670                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3671                 i = table->rows;
3672                 table->rows += mono_array_length (tb->interfaces);
3673                 alloc_table (table, table->rows);
3674                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3675                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3676                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3677                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3678                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3679                         values += MONO_INTERFACEIMPL_SIZE;
3680                 }
3681         }
3682
3683         /* handle fields */
3684         if (tb->fields) {
3685                 table = &assembly->tables [MONO_TABLE_FIELD];
3686                 table->rows += tb->num_fields;
3687                 alloc_table (table, table->rows);
3688                 for (i = 0; i < tb->num_fields; ++i)
3689                         mono_image_get_field_info (
3690                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3691         }
3692
3693         /* handle constructors */
3694         if (tb->ctors) {
3695                 table = &assembly->tables [MONO_TABLE_METHOD];
3696                 table->rows += mono_array_length (tb->ctors);
3697                 alloc_table (table, table->rows);
3698                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3699                         mono_image_get_ctor_info (domain,
3700                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3701         }
3702
3703         /* handle methods */
3704         if (tb->methods) {
3705                 table = &assembly->tables [MONO_TABLE_METHOD];
3706                 table->rows += tb->num_methods;
3707                 alloc_table (table, table->rows);
3708                 for (i = 0; i < tb->num_methods; ++i)
3709                         mono_image_get_method_info (
3710                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3711         }
3712
3713         /* Do the same with properties etc.. */
3714         if (tb->events && mono_array_length (tb->events)) {
3715                 table = &assembly->tables [MONO_TABLE_EVENT];
3716                 table->rows += mono_array_length (tb->events);
3717                 alloc_table (table, table->rows);
3718                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3719                 table->rows ++;
3720                 alloc_table (table, table->rows);
3721                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3722                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3723                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3724                 for (i = 0; i < mono_array_length (tb->events); ++i)
3725                         mono_image_get_event_info (
3726                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3727         }
3728         if (tb->properties && mono_array_length (tb->properties)) {
3729                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3730                 table->rows += mono_array_length (tb->properties);
3731                 alloc_table (table, table->rows);
3732                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3733                 table->rows ++;
3734                 alloc_table (table, table->rows);
3735                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3736                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3737                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3738                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3739                         mono_image_get_property_info (
3740                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3741         }
3742
3743         /* handle generic parameters */
3744         if (tb->generic_params) {
3745                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3746                 table->rows += mono_array_length (tb->generic_params);
3747                 alloc_table (table, table->rows);
3748                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3749                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3750
3751                         mono_image_get_generic_param_info (
3752                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3753                 }
3754         }
3755
3756         mono_image_add_decl_security (assembly, 
3757                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3758
3759         if (tb->subtypes) {
3760                 MonoDynamicTable *ntable;
3761                 
3762                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3763                 ntable->rows += mono_array_length (tb->subtypes);
3764                 alloc_table (ntable, ntable->rows);
3765                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3766
3767                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3768                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3769
3770                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3771                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3772                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3773                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3774                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3775                                 ntable->next_idx, ntable->rows);*/
3776                         values += MONO_NESTED_CLASS_SIZE;
3777                         ntable->next_idx++;
3778                 }
3779         }
3780 }
3781 #endif
3782
3783 static void
3784 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3785 {
3786         int i;
3787
3788         mono_ptr_array_append (*types, type);
3789
3790         if (!type->subtypes)
3791                 return;
3792
3793         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3794                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3795                 collect_types (types, subtype);
3796         }
3797 }
3798
3799 static gint
3800 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3801 {
3802         if ((*type1)->table_idx < (*type2)->table_idx)
3803                 return -1;
3804         else
3805                 if ((*type1)->table_idx > (*type2)->table_idx)
3806                         return 1;
3807         else
3808                 return 0;
3809 }
3810
3811 static void
3812 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3813         int i;
3814
3815         if (!pinfo)
3816                 return;
3817         for (i = 0; i < mono_array_length (pinfo); ++i) {
3818                 MonoReflectionParamBuilder *pb;
3819                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3820                 if (!pb)
3821                         continue;
3822                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3823         }
3824 }
3825
3826 static void
3827 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3828         int i;
3829         
3830         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3831         if (tb->fields) {
3832                 for (i = 0; i < tb->num_fields; ++i) {
3833                         MonoReflectionFieldBuilder* fb;
3834                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3835                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3836                 }
3837         }
3838         if (tb->events) {
3839                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3840                         MonoReflectionEventBuilder* eb;
3841                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3842                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3843                 }
3844         }
3845         if (tb->properties) {
3846                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3847                         MonoReflectionPropertyBuilder* pb;
3848                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3849                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3850                 }
3851         }
3852         if (tb->ctors) {
3853                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3854                         MonoReflectionCtorBuilder* cb;
3855                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3856                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3857                         params_add_cattrs (assembly, cb->pinfo);
3858                 }
3859         }
3860
3861         if (tb->methods) {
3862                 for (i = 0; i < tb->num_methods; ++i) {
3863                         MonoReflectionMethodBuilder* mb;
3864                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3865                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3866                         params_add_cattrs (assembly, mb->pinfo);
3867                 }
3868         }
3869
3870         if (tb->subtypes) {
3871                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3872                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3873         }
3874 }
3875
3876 static void
3877 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3878 {
3879         int i;
3880         
3881         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3882
3883         if (moduleb->global_methods) {
3884                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3885                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3886                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3887                         params_add_cattrs (assembly, mb->pinfo);
3888                 }
3889         }
3890
3891         if (moduleb->global_fields) {
3892                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3893                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3894                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3895                 }
3896         }
3897         
3898         if (moduleb->types) {
3899                 for (i = 0; i < moduleb->num_types; ++i)
3900                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3901         }
3902 }
3903
3904 static void
3905 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3906 {
3907         MonoDynamicTable *table;
3908         guint32 *values;
3909         char blob_size [6];
3910         guchar hash [20];
3911         char *b = blob_size;
3912         char *dir, *path;
3913
3914         table = &assembly->tables [MONO_TABLE_FILE];
3915         table->rows++;
3916         alloc_table (table, table->rows);
3917         values = table->values + table->next_idx * MONO_FILE_SIZE;
3918         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3919         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3920         if (image_is_dynamic (module->image)) {
3921                 /* This depends on the fact that the main module is emitted last */
3922                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3923                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3924         } else {
3925                 dir = NULL;
3926                 path = g_strdup (module->image->name);
3927         }
3928         mono_sha1_get_digest_from_file (path, hash);
3929         g_free (dir);
3930         g_free (path);
3931         mono_metadata_encode_value (20, b, &b);
3932         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3933         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3934         table->next_idx ++;
3935 }
3936
3937 static void
3938 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3939 {
3940         MonoDynamicTable *table;
3941         int i;
3942
3943         table = &assembly->tables [MONO_TABLE_MODULE];
3944         mb->table_idx = table->next_idx ++;
3945         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3946         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3947         i /= 16;
3948         ++i;
3949         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3950         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3951         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3952         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3953 }
3954
3955 static guint32
3956 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3957         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3958 {
3959         MonoDynamicTable *table;
3960         guint32 *values;
3961         guint32 visib, res;
3962
3963         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3964         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3965                 return 0;
3966
3967         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3968         table->rows++;
3969         alloc_table (table, table->rows);
3970         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3971
3972         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3973         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3974         if (klass->nested_in)
3975                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3976         else
3977                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3978         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3979         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3980
3981         res = table->next_idx;
3982
3983         table->next_idx ++;
3984
3985         /* Emit nested types */
3986         if (klass->ext && klass->ext->nested_classes) {
3987                 GList *tmp;
3988
3989                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3990                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3991         }
3992
3993         return res;
3994 }
3995
3996 static void
3997 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3998         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3999 {
4000         MonoClass *klass;
4001         guint32 idx, i;
4002
4003         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4004
4005         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4006
4007         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4008                                                                                                    parent_index, assembly);
4009
4010         /* 
4011          * Emit nested types
4012          * We need to do this ourselves since klass->nested_classes is not set up.
4013          */
4014         if (tb->subtypes) {
4015                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4016                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4017         }
4018 }
4019
4020 static void
4021 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4022         guint32 module_index, MonoDynamicImage *assembly)
4023 {
4024         MonoImage *image = module->image;
4025         MonoTableInfo  *t;
4026         guint32 i;
4027
4028         t = &image->tables [MONO_TABLE_TYPEDEF];
4029
4030         for (i = 0; i < t->rows; ++i) {
4031                 MonoError error;
4032                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4033                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4034
4035                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4036                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4037         }
4038 }
4039
4040 static void
4041 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4042 {
4043         MonoDynamicTable *table;
4044         guint32 *values;
4045         guint32 scope, scope_idx, impl, current_idx;
4046         gboolean forwarder = TRUE;
4047         gpointer iter = NULL;
4048         MonoClass *nested;
4049
4050         if (klass->nested_in) {
4051                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4052                 forwarder = FALSE;
4053         } else {
4054                 scope = resolution_scope_from_image (assembly, klass->image);
4055                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4056                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4057                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4058         }
4059
4060         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4061
4062         table->rows++;
4063         alloc_table (table, table->rows);
4064         current_idx = table->next_idx;
4065         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4066
4067         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4068         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4069         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4070         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4071         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4072
4073         table->next_idx++;
4074
4075         while ((nested = mono_class_get_nested_types (klass, &iter)))
4076                 add_exported_type (assemblyb, assembly, nested, current_idx);
4077 }
4078
4079 static void
4080 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4081 {
4082         MonoClass *klass;
4083         int i;
4084
4085         if (!assemblyb->type_forwarders)
4086                 return;
4087
4088         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4089                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4090                 MonoType *type;
4091                 if (!t)
4092                         continue;
4093
4094                 type = mono_reflection_type_get_handle (t);
4095                 g_assert (type);
4096
4097                 klass = mono_class_from_mono_type (type);
4098
4099                 add_exported_type (assemblyb, assembly, klass, 0);
4100         }
4101 }
4102
4103 #define align_pointer(base,p)\
4104         do {\
4105                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4106                 if (__diff & 3)\
4107                         (p) += 4 - (__diff & 3);\
4108         } while (0)
4109
4110 static int
4111 compare_constants (const void *a, const void *b)
4112 {
4113         const guint32 *a_values = (const guint32 *)a;
4114         const guint32 *b_values = (const guint32 *)b;
4115         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4116 }
4117
4118 static int
4119 compare_semantics (const void *a, const void *b)
4120 {
4121         const guint32 *a_values = (const guint32 *)a;
4122         const guint32 *b_values = (const guint32 *)b;
4123         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4124         if (assoc)
4125                 return assoc;
4126         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4127 }
4128
4129 static int
4130 compare_custom_attrs (const void *a, const void *b)
4131 {
4132         const guint32 *a_values = (const guint32 *)a;
4133         const guint32 *b_values = (const guint32 *)b;
4134
4135         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4136 }
4137
4138 static int
4139 compare_field_marshal (const void *a, const void *b)
4140 {
4141         const guint32 *a_values = (const guint32 *)a;
4142         const guint32 *b_values = (const guint32 *)b;
4143
4144         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4145 }
4146
4147 static int
4148 compare_nested (const void *a, const void *b)
4149 {
4150         const guint32 *a_values = (const guint32 *)a;
4151         const guint32 *b_values = (const guint32 *)b;
4152
4153         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4154 }
4155
4156 static int
4157 compare_genericparam (const void *a, const void *b)
4158 {
4159         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4160         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4161
4162         if ((*b_entry)->owner == (*a_entry)->owner)
4163                 return 
4164                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4165                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4166         else
4167                 return (*a_entry)->owner - (*b_entry)->owner;
4168 }
4169
4170 static int
4171 compare_declsecurity_attrs (const void *a, const void *b)
4172 {
4173         const guint32 *a_values = (const guint32 *)a;
4174         const guint32 *b_values = (const guint32 *)b;
4175
4176         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4177 }
4178
4179 static int
4180 compare_interface_impl (const void *a, const void *b)
4181 {
4182         const guint32 *a_values = (const guint32 *)a;
4183         const guint32 *b_values = (const guint32 *)b;
4184
4185         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4186         if (klass)
4187                 return klass;
4188
4189         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4190 }
4191
4192 static void
4193 pad_heap (MonoDynamicStream *sh)
4194 {
4195         if (sh->index & 3) {
4196                 int sz = 4 - (sh->index & 3);
4197                 memset (sh->data + sh->index, 0, sz);
4198                 sh->index += sz;
4199         }
4200 }
4201
4202 struct StreamDesc {
4203         const char *name;
4204         MonoDynamicStream *stream;
4205 };
4206
4207 /*
4208  * build_compressed_metadata() fills in the blob of data that represents the 
4209  * raw metadata as it will be saved in the PE file. The five streams are output 
4210  * and the metadata tables are comnpressed from the guint32 array representation, 
4211  * to the compressed on-disk format.
4212  */
4213 static void
4214 build_compressed_metadata (MonoDynamicImage *assembly)
4215 {
4216         MonoDynamicTable *table;
4217         int i;
4218         guint64 valid_mask = 0;
4219         guint64 sorted_mask;
4220         guint32 heapt_size = 0;
4221         guint32 meta_size = 256; /* allow for header and other stuff */
4222         guint32 table_offset;
4223         guint32 ntables = 0;
4224         guint64 *int64val;
4225         guint32 *int32val;
4226         guint16 *int16val;
4227         MonoImage *meta;
4228         unsigned char *p;
4229         struct StreamDesc stream_desc [5];
4230
4231         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4232         for (i = 0; i < assembly->gen_params->len; i++){
4233                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4234                 write_generic_param_entry (assembly, entry);
4235         }
4236
4237         stream_desc [0].name  = "#~";
4238         stream_desc [0].stream = &assembly->tstream;
4239         stream_desc [1].name  = "#Strings";
4240         stream_desc [1].stream = &assembly->sheap;
4241         stream_desc [2].name  = "#US";
4242         stream_desc [2].stream = &assembly->us;
4243         stream_desc [3].name  = "#Blob";
4244         stream_desc [3].stream = &assembly->blob;
4245         stream_desc [4].name  = "#GUID";
4246         stream_desc [4].stream = &assembly->guid;
4247         
4248         /* tables that are sorted */
4249         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4250                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4251                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4252                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4253                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4254                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4255                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4256         
4257         /* Compute table sizes */
4258         /* the MonoImage has already been created in mono_image_basic_init() */
4259         meta = &assembly->image;
4260
4261         /* sizes should be multiple of 4 */
4262         pad_heap (&assembly->blob);
4263         pad_heap (&assembly->guid);
4264         pad_heap (&assembly->sheap);
4265         pad_heap (&assembly->us);
4266
4267         /* Setup the info used by compute_sizes () */
4268         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4269         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4270         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4271
4272         meta_size += assembly->blob.index;
4273         meta_size += assembly->guid.index;
4274         meta_size += assembly->sheap.index;
4275         meta_size += assembly->us.index;
4276
4277         for (i=0; i < MONO_TABLE_NUM; ++i)
4278                 meta->tables [i].rows = assembly->tables [i].rows;
4279         
4280         for (i = 0; i < MONO_TABLE_NUM; i++){
4281                 if (meta->tables [i].rows == 0)
4282                         continue;
4283                 valid_mask |= (guint64)1 << i;
4284                 ntables ++;
4285                 meta->tables [i].row_size = mono_metadata_compute_size (
4286                         meta, i, &meta->tables [i].size_bitfield);
4287                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4288         }
4289         heapt_size += 24; /* #~ header size */
4290         heapt_size += ntables * 4;
4291         /* make multiple of 4 */
4292         heapt_size += 3;
4293         heapt_size &= ~3;
4294         meta_size += heapt_size;
4295         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4296         p = (unsigned char*)meta->raw_metadata;
4297         /* the metadata signature */
4298         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4299         /* version numbers and 4 bytes reserved */
4300         int16val = (guint16*)p;
4301         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4302         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4303         p += 8;
4304         /* version string */
4305         int32val = (guint32*)p;
4306         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4307         p += 4;
4308         memcpy (p, meta->version, strlen (meta->version));
4309         p += GUINT32_FROM_LE (*int32val);
4310         align_pointer (meta->raw_metadata, p);
4311         int16val = (guint16*)p;
4312         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4313         *int16val = GUINT16_TO_LE (5); /* number of streams */
4314         p += 4;
4315
4316         /*
4317          * write the stream info.
4318          */
4319         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4320         table_offset += 3; table_offset &= ~3;
4321
4322         assembly->tstream.index = heapt_size;
4323         for (i = 0; i < 5; ++i) {
4324                 int32val = (guint32*)p;
4325                 stream_desc [i].stream->offset = table_offset;
4326                 *int32val++ = GUINT32_TO_LE (table_offset);
4327                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4328                 table_offset += GUINT32_FROM_LE (*int32val);
4329                 table_offset += 3; table_offset &= ~3;
4330                 p += 8;
4331                 strcpy ((char*)p, stream_desc [i].name);
4332                 p += strlen (stream_desc [i].name) + 1;
4333                 align_pointer (meta->raw_metadata, p);
4334         }
4335         /* 
4336          * now copy the data, the table stream header and contents goes first.
4337          */
4338         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4339         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4340         int32val = (guint32*)p;
4341         *int32val = GUINT32_TO_LE (0); /* reserved */
4342         p += 4;
4343
4344         *p++ = 2; /* version */
4345         *p++ = 0;
4346
4347         if (meta->idx_string_wide)
4348                 *p |= 0x01;
4349         if (meta->idx_guid_wide)
4350                 *p |= 0x02;
4351         if (meta->idx_blob_wide)
4352                 *p |= 0x04;
4353         ++p;
4354         *p++ = 1; /* reserved */
4355         int64val = (guint64*)p;
4356         *int64val++ = GUINT64_TO_LE (valid_mask);
4357         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4358         p += 16;
4359         int32val = (guint32*)p;
4360         for (i = 0; i < MONO_TABLE_NUM; i++){
4361                 if (meta->tables [i].rows == 0)
4362                         continue;
4363                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4364         }
4365         p = (unsigned char*)int32val;
4366
4367         /* sort the tables that still need sorting */
4368         table = &assembly->tables [MONO_TABLE_CONSTANT];
4369         if (table->rows)
4370                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4371         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4372         if (table->rows)
4373                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4374         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4375         if (table->rows)
4376                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4377         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4378         if (table->rows)
4379                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4380         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4381         if (table->rows)
4382                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4383         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4384         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4385         if (table->rows)
4386                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4387         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4388         if (table->rows)
4389                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4390
4391         /* compress the tables */
4392         for (i = 0; i < MONO_TABLE_NUM; i++){
4393                 int row, col;
4394                 guint32 *values;
4395                 guint32 bitfield = meta->tables [i].size_bitfield;
4396                 if (!meta->tables [i].rows)
4397                         continue;
4398                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4399                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4400                 meta->tables [i].base = (char*)p;
4401                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4402                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4403                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4404                                 switch (mono_metadata_table_size (bitfield, col)) {
4405                                 case 1:
4406                                         *p++ = values [col];
4407                                         break;
4408                                 case 2:
4409                                         *p++ = values [col] & 0xff;
4410                                         *p++ = (values [col] >> 8) & 0xff;
4411                                         break;
4412                                 case 4:
4413                                         *p++ = values [col] & 0xff;
4414                                         *p++ = (values [col] >> 8) & 0xff;
4415                                         *p++ = (values [col] >> 16) & 0xff;
4416                                         *p++ = (values [col] >> 24) & 0xff;
4417                                         break;
4418                                 default:
4419                                         g_assert_not_reached ();
4420                                 }
4421                         }
4422                 }
4423                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4424         }
4425         
4426         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4427         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4428         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4429         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4430         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4431
4432         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4433 }
4434
4435 /*
4436  * Some tables in metadata need to be sorted according to some criteria, but
4437  * when methods and fields are first created with reflection, they may be assigned a token
4438  * that doesn't correspond to the final token they will get assigned after the sorting.
4439  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4440  * with the reflection objects that represent them. Once all the tables are set up, the 
4441  * reflection objects will contains the correct table index. fixup_method() will fixup the
4442  * tokens for the method with ILGenerator @ilgen.
4443  */
4444 static void
4445 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4446 {
4447         guint32 code_idx = GPOINTER_TO_UINT (value);
4448         MonoReflectionILTokenInfo *iltoken;
4449         MonoReflectionFieldBuilder *field;
4450         MonoReflectionCtorBuilder *ctor;
4451         MonoReflectionMethodBuilder *method;
4452         MonoReflectionTypeBuilder *tb;
4453         MonoReflectionArrayMethod *am;
4454         guint32 i, idx = 0;
4455         unsigned char *target;
4456
4457         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4458                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4459                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4460                 switch (target [3]) {
4461                 case MONO_TABLE_FIELD:
4462                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4463                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4464                                 idx = field->table_idx;
4465                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4466                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4467                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4468                         } else {
4469                                 g_assert_not_reached ();
4470                         }
4471                         break;
4472                 case MONO_TABLE_METHOD:
4473                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4474                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4475                                 idx = method->table_idx;
4476                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4477                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4478                                 idx = ctor->table_idx;
4479                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4480                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4481                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4482                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4483                         } else {
4484                                 g_assert_not_reached ();
4485                         }
4486                         break;
4487                 case MONO_TABLE_TYPEDEF:
4488                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4489                                 g_assert_not_reached ();
4490                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4491                         idx = tb->table_idx;
4492                         break;
4493                 case MONO_TABLE_MEMBERREF:
4494                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4495                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4496                                 idx = am->table_idx;
4497                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4498                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4499                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4500                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4501                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4502                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4503                                 continue;
4504                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4505                                 continue;
4506                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4507                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4508                                 g_assert (is_field_on_inst (f));
4509                                 continue;
4510                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4511                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4512                                 continue;
4513                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4514                                 continue;
4515                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4516                                 continue;
4517                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4518                                 continue;
4519                         } else {
4520                                 g_assert_not_reached ();
4521                         }
4522                         break;
4523                 case MONO_TABLE_METHODSPEC:
4524                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4525                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4526                                 g_assert (mono_method_signature (m)->generic_param_count);
4527                                 continue;
4528                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4529                                 continue;
4530                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4531                                 continue;
4532                         } else {
4533                                 g_assert_not_reached ();
4534                         }
4535                         break;
4536                 default:
4537                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4538                 }
4539                 target [0] = idx & 0xff;
4540                 target [1] = (idx >> 8) & 0xff;
4541                 target [2] = (idx >> 16) & 0xff;
4542         }
4543 }
4544
4545 /*
4546  * fixup_cattrs:
4547  *
4548  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4549  * value is not known when the table is emitted.
4550  */
4551 static void
4552 fixup_cattrs (MonoDynamicImage *assembly)
4553 {
4554         MonoDynamicTable *table;
4555         guint32 *values;
4556         guint32 type, i, idx, token;
4557         MonoObject *ctor;
4558
4559         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4560
4561         for (i = 0; i < table->rows; ++i) {
4562                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4563
4564                 type = values [MONO_CUSTOM_ATTR_TYPE];
4565                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4566                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4567                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4568                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4569                         g_assert (ctor);
4570
4571                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4572                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4573                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4574                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4575                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4576                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4577                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4578                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4579                         }
4580                 }
4581         }
4582 }
4583
4584 static void
4585 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4586 {
4587         MonoDynamicTable *table;
4588         guint32 *values;
4589
4590         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4591         table->rows++;
4592         alloc_table (table, table->rows);
4593         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4594         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4595         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4596         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4597         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4598         table->next_idx++;
4599 }
4600
4601 static void
4602 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4603 {
4604         MonoDynamicTable *table;
4605         guint32 *values;
4606         char blob_size [6];
4607         guchar hash [20];
4608         char *b = blob_size;
4609         char *name, *sname;
4610         guint32 idx, offset;
4611
4612         if (rsrc->filename) {
4613                 name = mono_string_to_utf8 (rsrc->filename);
4614                 sname = g_path_get_basename (name);
4615         
4616                 table = &assembly->tables [MONO_TABLE_FILE];
4617                 table->rows++;
4618                 alloc_table (table, table->rows);
4619                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4620                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4621                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4622                 g_free (sname);
4623
4624                 mono_sha1_get_digest_from_file (name, hash);
4625                 mono_metadata_encode_value (20, b, &b);
4626                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4627                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4628                 g_free (name);
4629                 idx = table->next_idx++;
4630                 rsrc->offset = 0;
4631                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4632         } else {
4633                 char sizebuf [4];
4634                 char *data;
4635                 guint len;
4636                 if (rsrc->data) {
4637                         data = mono_array_addr (rsrc->data, char, 0);
4638                         len = mono_array_length (rsrc->data);
4639                 } else {
4640                         data = NULL;
4641                         len = 0;
4642                 }
4643                 offset = len;
4644                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4645                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4646                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4647                 mono_image_add_stream_data (&assembly->resources, data, len);
4648
4649                 if (!mb->is_main)
4650                         /* 
4651                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4652                          * the main module, but that needs to reference the FILE table
4653                          * which isn't emitted yet.
4654                          */
4655                         return;
4656                 else
4657                         idx = 0;
4658         }
4659
4660         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4661 }
4662
4663 static void
4664 set_version_from_string (MonoString *version, guint32 *values)
4665 {
4666         gchar *ver, *p, *str;
4667         guint32 i;
4668         
4669         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4670         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4671         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4672         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4673         if (!version)
4674                 return;
4675         ver = str = mono_string_to_utf8 (version);
4676         for (i = 0; i < 4; ++i) {
4677                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4678                 switch (*p) {
4679                 case '.':
4680                         p++;
4681                         break;
4682                 case '*':
4683                         /* handle Revision and Build */
4684                         p++;
4685                         break;
4686                 }
4687                 ver = p;
4688         }
4689         g_free (str);
4690 }
4691
4692 static guint32
4693 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4694         gsize len;
4695         guint32 token = 0;
4696         char blob_size [6];
4697         char *b = blob_size;
4698
4699         if (!pkey)
4700                 return token;
4701
4702         len = mono_array_length (pkey);
4703         mono_metadata_encode_value (len, b, &b);
4704         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4705         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4706
4707         assembly->public_key = (guint8 *)g_malloc (len);
4708         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4709         assembly->public_key_len = len;
4710
4711         /* Special case: check for ECMA key (16 bytes) */
4712         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4713                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4714                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4715         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4716                 /* minimum key size (in 2.0) is 384 bits */
4717                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4718         } else {
4719                 /* FIXME - verifier */
4720                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4721                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4722         }
4723         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4724
4725         return token;
4726 }
4727
4728 static void
4729 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4730 {
4731         MonoDynamicTable *table;
4732         MonoDynamicImage *assembly;
4733         MonoReflectionAssemblyBuilder *assemblyb;
4734         MonoDomain *domain;
4735         guint32 *values;
4736         int i;
4737         guint32 module_index;
4738
4739         assemblyb = moduleb->assemblyb;
4740         assembly = moduleb->dynamic_image;
4741         domain = mono_object_domain (assemblyb);
4742
4743         /* Emit ASSEMBLY table */
4744         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4745         alloc_table (table, 1);
4746         values = table->values + MONO_ASSEMBLY_SIZE;
4747         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4748         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4749         if (assemblyb->culture) {
4750                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4751         } else {
4752                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4753         }
4754         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4755         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4756         set_version_from_string (assemblyb->version, values);
4757
4758         /* Emit FILE + EXPORTED_TYPE table */
4759         module_index = 0;
4760         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4761                 int j;
4762                 MonoReflectionModuleBuilder *file_module = 
4763                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4764                 if (file_module != moduleb) {
4765                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4766                         module_index ++;
4767                         if (file_module->types) {
4768                                 for (j = 0; j < file_module->num_types; ++j) {
4769                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4770                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4771                                 }
4772                         }
4773                 }
4774         }
4775         if (assemblyb->loaded_modules) {
4776                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4777                         MonoReflectionModule *file_module = 
4778                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4779                         mono_image_fill_file_table (domain, file_module, assembly);
4780                         module_index ++;
4781                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4782                 }
4783         }
4784         if (assemblyb->type_forwarders)
4785                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4786
4787         /* Emit MANIFESTRESOURCE table */
4788         module_index = 0;
4789         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4790                 int j;
4791                 MonoReflectionModuleBuilder *file_module = 
4792                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4793                 /* The table for the main module is emitted later */
4794                 if (file_module != moduleb) {
4795                         module_index ++;
4796                         if (file_module->resources) {
4797                                 int len = mono_array_length (file_module->resources);
4798                                 for (j = 0; j < len; ++j) {
4799                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4800                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4801                                 }
4802                         }
4803                 }
4804         }               
4805 }
4806
4807 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4808
4809 /*
4810  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4811  * for the modulebuilder @moduleb.
4812  * At the end of the process, method and field tokens are fixed up and the 
4813  * on-disk compressed metadata representation is created.
4814  */
4815 void
4816 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4817 {
4818         MonoDynamicTable *table;
4819         MonoDynamicImage *assembly;
4820         MonoReflectionAssemblyBuilder *assemblyb;
4821         MonoDomain *domain;
4822         MonoPtrArray types;
4823         guint32 *values;
4824         int i, j;
4825
4826         assemblyb = moduleb->assemblyb;
4827         assembly = moduleb->dynamic_image;
4828         domain = mono_object_domain (assemblyb);
4829
4830         if (assembly->text_rva)
4831                 return;
4832
4833         assembly->text_rva = START_TEXT_RVA;
4834
4835         if (moduleb->is_main) {
4836                 mono_image_emit_manifest (moduleb);
4837         }
4838
4839         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840         table->rows = 1; /* .<Module> */
4841         table->next_idx++;
4842         alloc_table (table, table->rows);
4843         /*
4844          * Set the first entry.
4845          */
4846         values = table->values + table->columns;
4847         values [MONO_TYPEDEF_FLAGS] = 0;
4848         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4849         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4850         values [MONO_TYPEDEF_EXTENDS] = 0;
4851         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4852         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4853
4854         /* 
4855          * handle global methods 
4856          * FIXME: test what to do when global methods are defined in multiple modules.
4857          */
4858         if (moduleb->global_methods) {
4859                 table = &assembly->tables [MONO_TABLE_METHOD];
4860                 table->rows += mono_array_length (moduleb->global_methods);
4861                 alloc_table (table, table->rows);
4862                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4863                         mono_image_get_method_info (
4864                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4865         }
4866         if (moduleb->global_fields) {
4867                 table = &assembly->tables [MONO_TABLE_FIELD];
4868                 table->rows += mono_array_length (moduleb->global_fields);
4869                 alloc_table (table, table->rows);
4870                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4871                         mono_image_get_field_info (
4872                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4873         }
4874
4875         table = &assembly->tables [MONO_TABLE_MODULE];
4876         alloc_table (table, 1);
4877         mono_image_fill_module_table (domain, moduleb, assembly);
4878
4879         /* Collect all types into a list sorted by their table_idx */
4880         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4881
4882         if (moduleb->types)
4883                 for (i = 0; i < moduleb->num_types; ++i) {
4884                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4885                         collect_types (&types, type);
4886                 }
4887
4888         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4889         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4890         table->rows += mono_ptr_array_size (types);
4891         alloc_table (table, table->rows);
4892
4893         /*
4894          * Emit type names + namespaces at one place inside the string heap,
4895          * so load_class_names () needs to touch fewer pages.
4896          */
4897         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4898                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4899                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4900         }
4901         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4902                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4903                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4904         }
4905
4906         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4907                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4908                 mono_image_get_type_info (domain, type, assembly);
4909         }
4910
4911         /* 
4912          * table->rows is already set above and in mono_image_fill_module_table.
4913          */
4914         /* add all the custom attributes at the end, once all the indexes are stable */
4915         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4916
4917         /* CAS assembly permissions */
4918         if (assemblyb->permissions_minimum)
4919                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4920         if (assemblyb->permissions_optional)
4921                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4922         if (assemblyb->permissions_refused)
4923                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4924
4925         module_add_cattrs (assembly, moduleb);
4926
4927         /* fixup tokens */
4928         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4929
4930         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4931          * the final tokens and don't need another fixup pass. */
4932
4933         if (moduleb->global_methods) {
4934                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4935                         MonoReflectionMethodBuilder *mb = mono_array_get (
4936                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4937                         mono_image_add_methodimpl (assembly, mb);
4938                 }
4939         }
4940
4941         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4942                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4943                 if (type->methods) {
4944                         for (j = 0; j < type->num_methods; ++j) {
4945                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4946                                         type->methods, MonoReflectionMethodBuilder*, j);
4947
4948                                 mono_image_add_methodimpl (assembly, mb);
4949                         }
4950                 }
4951         }
4952
4953         mono_ptr_array_destroy (types);
4954
4955         fixup_cattrs (assembly);
4956 }
4957
4958 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4959
4960 void
4961 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4962 {
4963         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4964 }
4965
4966 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4967
4968
4969 typedef struct {
4970         guint32 import_lookup_table;
4971         guint32 timestamp;
4972         guint32 forwarder;
4973         guint32 name_rva;
4974         guint32 import_address_table_rva;
4975 } MonoIDT;
4976
4977 typedef struct {
4978         guint32 name_rva;
4979         guint32 flags;
4980 } MonoILT;
4981
4982 #ifndef DISABLE_REFLECTION_EMIT
4983
4984 /*
4985  * mono_image_insert_string:
4986  * @module: module builder object
4987  * @str: a string
4988  *
4989  * Insert @str into the user string stream of @module.
4990  */
4991 guint32
4992 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4993 {
4994         MonoDynamicImage *assembly;
4995         guint32 idx;
4996         char buf [16];
4997         char *b = buf;
4998         
4999         if (!module->dynamic_image)
5000                 mono_image_module_basic_init (module);
5001
5002         assembly = module->dynamic_image;
5003         
5004         if (assembly->save) {
5005                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5006                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5007 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5008         {
5009                 char *swapped = g_malloc (2 * mono_string_length (str));
5010                 const char *p = (const char*)mono_string_chars (str);
5011
5012                 swap_with_size (swapped, p, 2, mono_string_length (str));
5013                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5014                 g_free (swapped);
5015         }
5016 #else
5017                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5018 #endif
5019                 mono_image_add_stream_data (&assembly->us, "", 1);
5020         } else {
5021                 idx = assembly->us.index ++;
5022         }
5023
5024         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5025
5026         return MONO_TOKEN_STRING | idx;
5027 }
5028
5029 guint32
5030 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5031 {
5032         MonoClass *klass;
5033         guint32 token = 0;
5034         MonoMethodSignature *sig;
5035
5036         klass = obj->vtable->klass;
5037         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5038                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5039                 MonoMethodSignature *old;
5040                 guint32 sig_token, parent;
5041                 int nargs, i;
5042
5043                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5044
5045                 nargs = mono_array_length (opt_param_types);
5046                 old = mono_method_signature (method);
5047                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5048
5049                 sig->hasthis = old->hasthis;
5050                 sig->explicit_this = old->explicit_this;
5051                 sig->call_convention = old->call_convention;
5052                 sig->generic_param_count = old->generic_param_count;
5053                 sig->param_count = old->param_count + nargs;
5054                 sig->sentinelpos = old->param_count;
5055                 sig->ret = old->ret;
5056
5057                 for (i = 0; i < old->param_count; i++)
5058                         sig->params [i] = old->params [i];
5059
5060                 for (i = 0; i < nargs; i++) {
5061                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5062                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5063                 }
5064
5065                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5066                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5067                 parent >>= MONO_TYPEDEFORREF_BITS;
5068
5069                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5070                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5071
5072                 sig_token = method_encode_signature (assembly, sig);
5073                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5074         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5075                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5076                 ReflectionMethodBuilder rmb;
5077                 guint32 parent, sig_token;
5078                 int nopt_args, nparams, ngparams, i;
5079                 char *name;
5080
5081                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5082                 rmb.opt_types = opt_param_types;
5083                 nopt_args = mono_array_length (opt_param_types);
5084
5085                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5086                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5087                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5088
5089                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5090                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5091                 sig->call_convention = rmb.call_conv;
5092                 sig->generic_param_count = ngparams;
5093                 sig->param_count = nparams + nopt_args;
5094                 sig->sentinelpos = nparams;
5095                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5096
5097                 for (i = 0; i < nparams; i++) {
5098                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5099                         sig->params [i] = mono_reflection_type_get_handle (rt);
5100                 }
5101
5102                 for (i = 0; i < nopt_args; i++) {
5103                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5104                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5105                 }
5106
5107                 sig_token = method_builder_encode_signature (assembly, &rmb);
5108
5109                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5110                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5111
5112                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5113                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5114
5115                 name = mono_string_to_utf8 (rmb.name);
5116                 token = mono_image_get_varargs_method_token (
5117                         assembly, parent, name, sig_token);
5118                 g_free (name);
5119         } else {
5120                 g_error ("requested method token for %s\n", klass->name);
5121         }
5122
5123         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5124         register_dyn_token (assembly, token, obj);
5125         return token;
5126 }
5127
5128 /*
5129  * mono_image_create_token:
5130  * @assembly: a dynamic assembly
5131  * @obj:
5132  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5133  *
5134  * Get a token to insert in the IL code stream for the given MemberInfo.
5135  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5136  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5137  * entry.
5138  */
5139 guint32
5140 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5141                                                  gboolean create_open_instance, gboolean register_token)
5142 {
5143         MonoClass *klass;
5144         guint32 token = 0;
5145
5146         klass = obj->vtable->klass;
5147
5148         /* Check for user defined reflection objects */
5149         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5150         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5151                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5152
5153         if (strcmp (klass->name, "MethodBuilder") == 0) {
5154                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5155                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5156
5157                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5158                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5159                 else
5160                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5161                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5162         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5163                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5164                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5165
5166                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5167                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5168                 else
5169                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5170                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5171         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5172                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5173                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5174                 if (tb->generic_params) {
5175                         token = mono_image_get_generic_field_token (assembly, fb);
5176                 } else {
5177                         if (tb->module->dynamic_image == assembly) {
5178                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5179                         } else {
5180                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5181                         }
5182                 }
5183         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5184                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5185                 if (create_open_instance && tb->generic_params) {
5186                         MonoType *type;
5187                         init_type_builder_generics (obj);
5188                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5190                         token = mono_metadata_token_from_dor (token);
5191                 } else if (tb->module->dynamic_image == assembly) {
5192                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5193                 } else {
5194                         MonoType *type;
5195                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5196                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5197                 }
5198         } else if (strcmp (klass->name, "MonoType") == 0) {
5199                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5200                 MonoClass *mc = mono_class_from_mono_type (type);
5201                 token = mono_metadata_token_from_dor (
5202                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5203         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5204                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5205                 token = mono_metadata_token_from_dor (
5206                         mono_image_typedef_or_ref (assembly, type));
5207         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5208                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5209                 token = mono_metadata_token_from_dor (
5210                         mono_image_typedef_or_ref (assembly, type));
5211         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5212                    strcmp (klass->name, "MonoMethod") == 0 ||
5213                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5214                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5215                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5216                 if (m->method->is_inflated) {
5217                         if (create_open_instance)
5218                                 token = mono_image_get_methodspec_token (assembly, m->method);
5219                         else
5220                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5221                 } else if ((m->method->klass->image == &assembly->image) &&
5222                          !m->method->klass->generic_class) {
5223                         static guint32 method_table_idx = 0xffffff;
5224                         if (m->method->klass->wastypebuilder) {
5225                                 /* we use the same token as the one that was assigned
5226                                  * to the Methodbuilder.
5227                                  * FIXME: do the equivalent for Fields.
5228                                  */
5229                                 token = m->method->token;
5230                         } else {
5231                                 /*
5232                                  * Each token should have a unique index, but the indexes are
5233                                  * assigned by managed code, so we don't know about them. An
5234                                  * easy solution is to count backwards...
5235                                  */
5236                                 method_table_idx --;
5237                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5238                         }
5239                 } else {
5240                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5241                 }
5242                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5243         } else if (strcmp (klass->name, "MonoField") == 0) {
5244                 MonoReflectionField *f = (MonoReflectionField *)obj;
5245                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5246                         static guint32 field_table_idx = 0xffffff;
5247                         field_table_idx --;
5248                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5249                 } else {
5250                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5251                 }
5252                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5253         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5254                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5255                 token = mono_image_get_array_token (assembly, m);
5256         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5257                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5258                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5259         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5260                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5261                 token = mono_metadata_token_from_dor (
5262                         mono_image_typedef_or_ref (assembly, type));
5263         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5264                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5265                 token = mono_image_get_field_on_inst_token (assembly, f);
5266         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5267                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5268                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5269         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5270                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5271                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5272         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5273                 MonoReflectionType *type = (MonoReflectionType *)obj;
5274                 token = mono_metadata_token_from_dor (
5275                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5276         } else {
5277                 g_error ("requested token for %s\n", klass->name);
5278         }
5279
5280         if (register_token)
5281                 mono_image_register_token (assembly, token, obj);
5282
5283         return token;
5284 }
5285
5286 /*
5287  * mono_image_register_token:
5288  *
5289  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5290  * the Module.ResolveXXXToken () methods to work.
5291  */
5292 void
5293 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5294 {
5295         MonoObject *prev;
5296
5297         dynamic_image_lock (assembly);
5298         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5299         if (prev) {
5300                 /* There could be multiple MethodInfo objects with the same token */
5301                 //g_assert (prev == obj);
5302         } else {
5303                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5304         }
5305         dynamic_image_unlock (assembly);
5306 }
5307
5308 static MonoDynamicImage*
5309 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5310 {
5311         static const guchar entrycode [16] = {0xff, 0x25, 0};
5312         MonoDynamicImage *image;
5313         int i;
5314
5315         const char *version;
5316
5317         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5318                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5319         else
5320                 version = mono_get_runtime_info ()->runtime_version;
5321
5322 #if HAVE_BOEHM_GC
5323         /* The MonoGHashTable's need GC tracking */
5324         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5325 #else
5326         image = g_new0 (MonoDynamicImage, 1);
5327 #endif
5328
5329         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5330         
5331         /*g_print ("created image %p\n", image);*/
5332         /* keep in sync with image.c */
5333         image->image.name = assembly_name;
5334         image->image.assembly_name = image->image.name; /* they may be different */
5335         image->image.module_name = module_name;
5336         image->image.version = g_strdup (version);
5337         image->image.md_version_major = 1;
5338         image->image.md_version_minor = 1;
5339         image->image.dynamic = TRUE;
5340
5341         image->image.references = g_new0 (MonoAssembly*, 1);
5342         image->image.references [0] = NULL;
5343
5344         mono_image_init (&image->image);
5345
5346         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");
5347         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5348         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5349         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5350         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5351         image->handleref = g_hash_table_new (NULL, NULL);
5352         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");
5353         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5354         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");
5355         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");
5356         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5357         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5358         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5359         image->gen_params = g_ptr_array_new ();
5360         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5361
5362         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5363         string_heap_init (&image->sheap);
5364         mono_image_add_stream_data (&image->us, "", 1);
5365         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5366         /* import tables... */
5367         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5368         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5369         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5370         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5371         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5372         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5373         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5374         stream_data_align (&image->code);
5375
5376         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5377
5378         for (i=0; i < MONO_TABLE_NUM; ++i) {
5379                 image->tables [i].next_idx = 1;
5380                 image->tables [i].columns = table_sizes [i];
5381         }
5382
5383         image->image.assembly = (MonoAssembly*)assembly;
5384         image->run = assembly->run;
5385         image->save = assembly->save;
5386         image->pe_kind = 0x1; /* ILOnly */
5387         image->machine = 0x14c; /* I386 */
5388         
5389         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5390
5391         dynamic_images_lock ();
5392
5393         if (!dynamic_images)
5394                 dynamic_images = g_ptr_array_new ();
5395
5396         g_ptr_array_add (dynamic_images, image);
5397
5398         dynamic_images_unlock ();
5399
5400         return image;
5401 }
5402 #endif
5403
5404 static void
5405 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5406 {
5407         g_free (key);
5408 }
5409
5410 static void
5411 release_hashtable (MonoGHashTable **hash)
5412 {
5413         if (*hash) {
5414                 mono_g_hash_table_destroy (*hash);
5415                 *hash = NULL;
5416         }
5417 }
5418
5419 void
5420 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5421 {
5422         release_hashtable (&image->token_fixups);
5423         release_hashtable (&image->handleref_managed);
5424         release_hashtable (&image->tokens);
5425         release_hashtable (&image->remapped_tokens);
5426         release_hashtable (&image->generic_def_objects);
5427         release_hashtable (&image->methodspec);
5428 }
5429
5430 // Free dynamic image pass one: Free resources but not image itself
5431 void
5432 mono_dynamic_image_free (MonoDynamicImage *image)
5433 {
5434         MonoDynamicImage *di = image;
5435         GList *list;
5436         int i;
5437
5438         if (di->methodspec)
5439                 mono_g_hash_table_destroy (di->methodspec);
5440         if (di->typespec)
5441                 g_hash_table_destroy (di->typespec);
5442         if (di->typeref)
5443                 g_hash_table_destroy (di->typeref);
5444         if (di->handleref)
5445                 g_hash_table_destroy (di->handleref);
5446         if (di->handleref_managed)
5447                 mono_g_hash_table_destroy (di->handleref_managed);
5448         if (di->tokens)
5449                 mono_g_hash_table_destroy (di->tokens);
5450         if (di->remapped_tokens)
5451                 mono_g_hash_table_destroy (di->remapped_tokens);
5452         if (di->generic_def_objects)
5453                 mono_g_hash_table_destroy (di->generic_def_objects);
5454         if (di->blob_cache) {
5455                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5456                 g_hash_table_destroy (di->blob_cache);
5457         }
5458         if (di->standalonesig_cache)
5459                 g_hash_table_destroy (di->standalonesig_cache);
5460         for (list = di->array_methods; list; list = list->next) {
5461                 ArrayMethod *am = (ArrayMethod *)list->data;
5462                 g_free (am->sig);
5463                 g_free (am->name);
5464                 g_free (am);
5465         }
5466         g_list_free (di->array_methods);
5467         if (di->gen_params) {
5468                 for (i = 0; i < di->gen_params->len; i++) {
5469                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5470                         mono_gc_deregister_root ((char*) &entry->gparam);
5471                         g_free (entry);
5472                 }
5473                 g_ptr_array_free (di->gen_params, TRUE);
5474         }
5475         if (di->token_fixups)
5476                 mono_g_hash_table_destroy (di->token_fixups);
5477         if (di->method_to_table_idx)
5478                 g_hash_table_destroy (di->method_to_table_idx);
5479         if (di->field_to_table_idx)
5480                 g_hash_table_destroy (di->field_to_table_idx);
5481         if (di->method_aux_hash)
5482                 g_hash_table_destroy (di->method_aux_hash);
5483         if (di->vararg_aux_hash)
5484                 g_hash_table_destroy (di->vararg_aux_hash);
5485         g_free (di->strong_name);
5486         g_free (di->win32_res);
5487         if (di->public_key)
5488                 g_free (di->public_key);
5489
5490         /*g_print ("string heap destroy for image %p\n", di);*/
5491         mono_dynamic_stream_reset (&di->sheap);
5492         mono_dynamic_stream_reset (&di->code);
5493         mono_dynamic_stream_reset (&di->resources);
5494         mono_dynamic_stream_reset (&di->us);
5495         mono_dynamic_stream_reset (&di->blob);
5496         mono_dynamic_stream_reset (&di->tstream);
5497         mono_dynamic_stream_reset (&di->guid);
5498         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5499                 g_free (di->tables [i].values);
5500         }
5501
5502         dynamic_images_lock ();
5503
5504         if (dynamic_images)
5505                 g_ptr_array_remove (dynamic_images, di);
5506
5507         dynamic_images_unlock ();
5508 }
5509
5510 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5511 void
5512 mono_dynamic_image_free_image (MonoDynamicImage *image)
5513 {
5514         /* See create_dynamic_mono_image () */
5515 #if HAVE_BOEHM_GC
5516         /* Allocated using GC_MALLOC */
5517 #else
5518         g_free (image);
5519 #endif
5520 }
5521
5522 #ifndef DISABLE_REFLECTION_EMIT
5523
5524 /*
5525  * mono_image_basic_init:
5526  * @assembly: an assembly builder object
5527  *
5528  * Create the MonoImage that represents the assembly builder and setup some
5529  * of the helper hash table and the basic metadata streams.
5530  */
5531 void
5532 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5533 {
5534         MonoDynamicAssembly *assembly;
5535         MonoDynamicImage *image;
5536         MonoDomain *domain = mono_object_domain (assemblyb);
5537         
5538         if (assemblyb->dynamic_assembly)
5539                 return;
5540
5541 #if HAVE_BOEHM_GC
5542         /* assembly->assembly.image might be GC allocated */
5543         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5544 #else
5545         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5546 #endif
5547
5548         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5549         
5550         assembly->assembly.ref_count = 1;
5551         assembly->assembly.dynamic = TRUE;
5552         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5553         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5554         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5555         if (assemblyb->culture)
5556                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5557         else
5558                 assembly->assembly.aname.culture = g_strdup ("");
5559
5560         if (assemblyb->version) {
5561                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5562                         char **version = g_strsplit (vstr, ".", 4);
5563                         char **parts = version;
5564                         assembly->assembly.aname.major = atoi (*parts++);
5565                         assembly->assembly.aname.minor = atoi (*parts++);
5566                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5567                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5568
5569                         g_strfreev (version);
5570                         g_free (vstr);
5571         } else {
5572                         assembly->assembly.aname.major = 0;
5573                         assembly->assembly.aname.minor = 0;
5574                         assembly->assembly.aname.build = 0;
5575                         assembly->assembly.aname.revision = 0;
5576         }
5577
5578         assembly->run = assemblyb->access != 2;
5579         assembly->save = assemblyb->access != 1;
5580         assembly->domain = domain;
5581
5582         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5583         image->initial_image = TRUE;
5584         assembly->assembly.aname.name = image->image.name;
5585         assembly->assembly.image = &image->image;
5586         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5587                 /* -1 to correct for the trailing NULL byte */
5588                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5589                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5590                 }
5591                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5592         }
5593
5594         mono_domain_assemblies_lock (domain);
5595         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5596         mono_domain_assemblies_unlock (domain);
5597
5598         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5599         
5600         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5601         
5602         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5603 }
5604
5605 #endif /* !DISABLE_REFLECTION_EMIT */
5606
5607 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5608
5609 static int
5610 calc_section_size (MonoDynamicImage *assembly)
5611 {
5612         int nsections = 0;
5613
5614         /* alignment constraints */
5615         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5616         g_assert ((assembly->code.index % 4) == 0);
5617         assembly->meta_size += 3;
5618         assembly->meta_size &= ~3;
5619         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5620         g_assert ((assembly->resources.index % 4) == 0);
5621
5622         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5623         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5624         nsections++;
5625
5626         if (assembly->win32_res) {
5627                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5628
5629                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5630                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5631                 nsections++;
5632         }
5633
5634         assembly->sections [MONO_SECTION_RELOC].size = 12;
5635         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5636         nsections++;
5637
5638         return nsections;
5639 }
5640
5641 typedef struct {
5642         guint32 id;
5643         guint32 offset;
5644         GSList *children;
5645         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5646 } ResTreeNode;
5647
5648 static int
5649 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5650 {
5651         ResTreeNode *t1 = (ResTreeNode*)a;
5652         ResTreeNode *t2 = (ResTreeNode*)b;
5653
5654         return t1->id - t2->id;
5655 }
5656
5657 /*
5658  * resource_tree_create:
5659  *
5660  *  Organize the resources into a resource tree.
5661  */
5662 static ResTreeNode *
5663 resource_tree_create (MonoArray *win32_resources)
5664 {
5665         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5666         GSList *l;
5667         int i;
5668
5669         tree = g_new0 (ResTreeNode, 1);
5670         
5671         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5672                 MonoReflectionWin32Resource *win32_res =
5673                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5674
5675                 /* Create node */
5676
5677                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5678                 lang_node = g_new0 (ResTreeNode, 1);
5679                 lang_node->id = win32_res->lang_id;
5680                 lang_node->win32_res = win32_res;
5681
5682                 /* Create type node if neccesary */
5683                 type_node = NULL;
5684                 for (l = tree->children; l; l = l->next)
5685                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5686                                 type_node = (ResTreeNode*)l->data;
5687                                 break;
5688                         }
5689
5690                 if (!type_node) {
5691                         type_node = g_new0 (ResTreeNode, 1);
5692                         type_node->id = win32_res->res_type;
5693
5694                         /* 
5695                          * The resource types have to be sorted otherwise
5696                          * Windows Explorer can't display the version information.
5697                          */
5698                         tree->children = g_slist_insert_sorted (tree->children, 
5699                                 type_node, resource_tree_compare_by_id);
5700                 }
5701
5702                 /* Create res node if neccesary */
5703                 res_node = NULL;
5704                 for (l = type_node->children; l; l = l->next)
5705                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5706                                 res_node = (ResTreeNode*)l->data;
5707                                 break;
5708                         }
5709
5710                 if (!res_node) {
5711                         res_node = g_new0 (ResTreeNode, 1);
5712                         res_node->id = win32_res->res_id;
5713                         type_node->children = g_slist_append (type_node->children, res_node);
5714                 }
5715
5716                 res_node->children = g_slist_append (res_node->children, lang_node);
5717         }
5718
5719         return tree;
5720 }
5721
5722 /*
5723  * resource_tree_encode:
5724  * 
5725  *   Encode the resource tree into the format used in the PE file.
5726  */
5727 static void
5728 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5729 {
5730         char *entries;
5731         MonoPEResourceDir dir;
5732         MonoPEResourceDirEntry dir_entry;
5733         MonoPEResourceDataEntry data_entry;
5734         GSList *l;
5735         guint32 res_id_entries;
5736
5737         /*
5738          * For the format of the resource directory, see the article
5739          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5740          * Matt Pietrek
5741          */
5742
5743         memset (&dir, 0, sizeof (dir));
5744         memset (&dir_entry, 0, sizeof (dir_entry));
5745         memset (&data_entry, 0, sizeof (data_entry));
5746
5747         g_assert (sizeof (dir) == 16);
5748         g_assert (sizeof (dir_entry) == 8);
5749         g_assert (sizeof (data_entry) == 16);
5750
5751         node->offset = p - begin;
5752
5753         /* IMAGE_RESOURCE_DIRECTORY */
5754         res_id_entries = g_slist_length (node->children);
5755         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5756
5757         memcpy (p, &dir, sizeof (dir));
5758         p += sizeof (dir);
5759
5760         /* Reserve space for entries */
5761         entries = p;
5762         p += sizeof (dir_entry) * res_id_entries;
5763
5764         /* Write children */
5765         for (l = node->children; l; l = l->next) {
5766                 ResTreeNode *child = (ResTreeNode*)l->data;
5767
5768                 if (child->win32_res) {
5769                         guint32 size;
5770
5771                         child->offset = p - begin;
5772
5773                         /* IMAGE_RESOURCE_DATA_ENTRY */
5774                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5775                         size = mono_array_length (child->win32_res->res_data);
5776                         data_entry.rde_size = GUINT32_TO_LE (size);
5777
5778                         memcpy (p, &data_entry, sizeof (data_entry));
5779                         p += sizeof (data_entry);
5780
5781                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5782                         p += size;
5783                 } else {
5784                         resource_tree_encode (child, begin, p, &p);
5785                 }
5786         }
5787
5788         /* IMAGE_RESOURCE_ENTRY */
5789         for (l = node->children; l; l = l->next) {
5790                 ResTreeNode *child = (ResTreeNode*)l->data;
5791
5792                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5793                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5794
5795                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5796                 entries += sizeof (dir_entry);
5797         }
5798
5799         *endbuf = p;
5800 }
5801
5802 static void
5803 resource_tree_free (ResTreeNode * node)
5804 {
5805         GSList * list;
5806         for (list = node->children; list; list = list->next)
5807                 resource_tree_free ((ResTreeNode*)list->data);
5808         g_slist_free(node->children);
5809         g_free (node);
5810 }
5811
5812 static void
5813 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5814 {
5815         char *buf;
5816         char *p;
5817         guint32 size, i;
5818         MonoReflectionWin32Resource *win32_res;
5819         ResTreeNode *tree;
5820
5821         if (!assemblyb->win32_resources)
5822                 return;
5823
5824         /*
5825          * Resources are stored in a three level tree inside the PE file.
5826          * - level one contains a node for each type of resource
5827          * - level two contains a node for each resource
5828          * - level three contains a node for each instance of a resource for a
5829          *   specific language.
5830          */
5831
5832         tree = resource_tree_create (assemblyb->win32_resources);
5833
5834         /* Estimate the size of the encoded tree */
5835         size = 0;
5836         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5837                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5838                 size += mono_array_length (win32_res->res_data);
5839         }
5840         /* Directory structure */
5841         size += mono_array_length (assemblyb->win32_resources) * 256;
5842         p = buf = (char *)g_malloc (size);
5843
5844         resource_tree_encode (tree, p, p, &p);
5845
5846         g_assert (p - buf <= size);
5847
5848         assembly->win32_res = (char *)g_malloc (p - buf);
5849         assembly->win32_res_size = p - buf;
5850         memcpy (assembly->win32_res, buf, p - buf);
5851
5852         g_free (buf);
5853         resource_tree_free (tree);
5854 }
5855
5856 static void
5857 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5858 {
5859         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5860         int i;
5861
5862         p += sizeof (MonoPEResourceDir);
5863         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5864                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5865                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5866                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5867                         fixup_resource_directory (res_section, child, rva);
5868                 } else {
5869                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5870                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5871                 }
5872
5873                 p += sizeof (MonoPEResourceDirEntry);
5874         }
5875 }
5876
5877 static void
5878 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5879 {
5880         guint32 dummy;
5881         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5882                 g_error ("WriteFile returned %d\n", GetLastError ());
5883 }
5884
5885 /*
5886  * mono_image_create_pefile:
5887  * @mb: a module builder object
5888  * 
5889  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5890  * assembly->pefile where it can be easily retrieved later in chunks.
5891  */
5892 void
5893 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5894 {
5895         MonoMSDOSHeader *msdos;
5896         MonoDotNetHeader *header;
5897         MonoSectionTable *section;
5898         MonoCLIHeader *cli_header;
5899         guint32 size, image_size, virtual_base, text_offset;
5900         guint32 header_start, section_start, file_offset, virtual_offset;
5901         MonoDynamicImage *assembly;
5902         MonoReflectionAssemblyBuilder *assemblyb;
5903         MonoDynamicStream pefile_stream = {0};
5904         MonoDynamicStream *pefile = &pefile_stream;
5905         int i, nsections;
5906         guint32 *rva, value;
5907         guchar *p;
5908         static const unsigned char msheader[] = {
5909                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5910                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5911                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5912                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5913                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5914                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5915                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5916                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5917         };
5918
5919         assemblyb = mb->assemblyb;
5920
5921         mono_image_basic_init (assemblyb);
5922         assembly = mb->dynamic_image;
5923
5924         assembly->pe_kind = assemblyb->pe_kind;
5925         assembly->machine = assemblyb->machine;
5926         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5927         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5928         
5929         mono_image_build_metadata (mb);
5930
5931         if (mb->is_main && assemblyb->resources) {
5932                 int len = mono_array_length (assemblyb->resources);
5933                 for (i = 0; i < len; ++i)
5934                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5935         }
5936
5937         if (mb->resources) {
5938                 int len = mono_array_length (mb->resources);
5939                 for (i = 0; i < len; ++i)
5940                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5941         }
5942
5943         build_compressed_metadata (assembly);
5944
5945         if (mb->is_main)
5946                 assembly_add_win32_resources (assembly, assemblyb);
5947
5948         nsections = calc_section_size (assembly);
5949         
5950         /* The DOS header and stub */
5951         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5952         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5953
5954         /* the dotnet header */
5955         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5956
5957         /* the section tables */
5958         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5959
5960         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5961         virtual_offset = VIRT_ALIGN;
5962         image_size = 0;
5963
5964         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5965                 if (!assembly->sections [i].size)
5966                         continue;
5967                 /* align offsets */
5968                 file_offset += FILE_ALIGN - 1;
5969                 file_offset &= ~(FILE_ALIGN - 1);
5970                 virtual_offset += VIRT_ALIGN - 1;
5971                 virtual_offset &= ~(VIRT_ALIGN - 1);
5972
5973                 assembly->sections [i].offset = file_offset;
5974                 assembly->sections [i].rva = virtual_offset;
5975
5976                 file_offset += assembly->sections [i].size;
5977                 virtual_offset += assembly->sections [i].size;
5978                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5979         }
5980
5981         file_offset += FILE_ALIGN - 1;
5982         file_offset &= ~(FILE_ALIGN - 1);
5983
5984         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5985
5986         /* back-patch info */
5987         msdos = (MonoMSDOSHeader*)pefile->data;
5988         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5989
5990         header = (MonoDotNetHeader*)(pefile->data + header_start);
5991         header->pesig [0] = 'P';
5992         header->pesig [1] = 'E';
5993         
5994         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5995         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5996         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5997         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5998         if (assemblyb->pekind == 1) {
5999                 /* it's a dll */
6000                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6001         } else {
6002                 /* it's an exe */
6003                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6004         }
6005
6006         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6007
6008         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6009         header->pe.pe_major = 6;
6010         header->pe.pe_minor = 0;
6011         size = assembly->sections [MONO_SECTION_TEXT].size;
6012         size += FILE_ALIGN - 1;
6013         size &= ~(FILE_ALIGN - 1);
6014         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6015         size = assembly->sections [MONO_SECTION_RSRC].size;
6016         size += FILE_ALIGN - 1;
6017         size &= ~(FILE_ALIGN - 1);
6018         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6019         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6020         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6021         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6022         /* pe_rva_entry_point always at the beginning of the text section */
6023         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6024
6025         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6026         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6027         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6028         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6029         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6030         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6031         size = section_start;
6032         size += FILE_ALIGN - 1;
6033         size &= ~(FILE_ALIGN - 1);
6034         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6035         size = image_size;
6036         size += VIRT_ALIGN - 1;
6037         size &= ~(VIRT_ALIGN - 1);
6038         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6039
6040         /*
6041         // Translate the PEFileKind value to the value expected by the Windows loader
6042         */
6043         {
6044                 short kind;
6045
6046                 /*
6047                 // PEFileKinds.Dll == 1
6048                 // PEFileKinds.ConsoleApplication == 2
6049                 // PEFileKinds.WindowApplication == 3
6050                 //
6051                 // need to get:
6052                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6053                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6054                 */
6055                 if (assemblyb->pekind == 3)
6056                         kind = 2;
6057                 else
6058                         kind = 3;
6059                 
6060                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6061         }    
6062         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6063         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6064         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6065         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6066         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6067         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6068
6069         /* fill data directory entries */
6070
6071         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6072         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6073
6074         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6075         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6076
6077         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6078         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6079         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6080         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6081         /* patch entrypoint name */
6082         if (assemblyb->pekind == 1)
6083                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6084         else
6085                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6086         /* patch imported function RVA name */
6087         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6088         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6089
6090         /* the import table */
6091         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6092         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6093         /* patch imported dll RVA name and other entries in the dir */
6094         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6095         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6096         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6097         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6098         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6099         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6100
6101         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6102         value = (assembly->text_rva + assembly->imp_names_offset);
6103         *p++ = (value) & 0xff;
6104         *p++ = (value >> 8) & (0xff);
6105         *p++ = (value >> 16) & (0xff);
6106         *p++ = (value >> 24) & (0xff);
6107
6108         /* the CLI header info */
6109         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6110         cli_header->ch_size = GUINT32_FROM_LE (72);
6111         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6112         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6113         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6114         if (assemblyb->entry_point) {
6115                 guint32 table_idx = 0;
6116                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6117                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6118                         table_idx = methodb->table_idx;
6119                 } else {
6120                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6121                 }
6122                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6123         } else {
6124                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6125         }
6126         /* The embedded managed resources */
6127         text_offset = assembly->text_rva + assembly->code.index;
6128         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6129         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6130         text_offset += assembly->resources.index;
6131         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6132         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6133         text_offset += assembly->meta_size;
6134         if (assembly->strong_name_size) {
6135                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6136                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6137                 text_offset += assembly->strong_name_size;
6138         }
6139
6140         /* write the section tables and section content */
6141         section = (MonoSectionTable*)(pefile->data + section_start);
6142         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6143                 static const char section_names [][7] = {
6144                         ".text", ".rsrc", ".reloc"
6145                 };
6146                 if (!assembly->sections [i].size)
6147                         continue;
6148                 strcpy (section->st_name, section_names [i]);
6149                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6150                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6151                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6152                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6153                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6154                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6155                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6156                 section ++;
6157         }
6158         
6159         checked_write_file (file, pefile->data, pefile->index);
6160         
6161         mono_dynamic_stream_reset (pefile);
6162         
6163         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6164                 if (!assembly->sections [i].size)
6165                         continue;
6166                 
6167                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6168                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6169                 
6170                 switch (i) {
6171                 case MONO_SECTION_TEXT:
6172                         /* patch entry point */
6173                         p = (guchar*)(assembly->code.data + 2);
6174                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6175                         *p++ = (value) & 0xff;
6176                         *p++ = (value >> 8) & 0xff;
6177                         *p++ = (value >> 16) & 0xff;
6178                         *p++ = (value >> 24) & 0xff;
6179                 
6180                         checked_write_file (file, assembly->code.data, assembly->code.index);
6181                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6182                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6183                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6184                                 
6185
6186                         g_free (assembly->image.raw_metadata);
6187                         break;
6188                 case MONO_SECTION_RELOC: {
6189                         struct {
6190                                 guint32 page_rva;
6191                                 guint32 block_size;
6192                                 guint16 type_and_offset;
6193                                 guint16 term;
6194                         } reloc;
6195                         
6196                         g_assert (sizeof (reloc) == 12);
6197                         
6198                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6199                         reloc.block_size = GUINT32_FROM_LE (12);
6200                         
6201                         /* 
6202                          * the entrypoint is always at the start of the text section 
6203                          * 3 is IMAGE_REL_BASED_HIGHLOW
6204                          * 2 is patch_size_rva - text_rva
6205                          */
6206                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6207                         reloc.term = 0;
6208                         
6209                         checked_write_file (file, &reloc, sizeof (reloc));
6210                         
6211                         break;
6212                 }
6213                 case MONO_SECTION_RSRC:
6214                         if (assembly->win32_res) {
6215
6216                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6217                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6218                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6219                         }
6220                         break;
6221                 default:
6222                         g_assert_not_reached ();
6223                 }
6224         }
6225         
6226         /* check that the file is properly padded */
6227         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6228                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6229         if (! SetEndOfFile (file))
6230                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6231         
6232         mono_dynamic_stream_reset (&assembly->code);
6233         mono_dynamic_stream_reset (&assembly->us);
6234         mono_dynamic_stream_reset (&assembly->blob);
6235         mono_dynamic_stream_reset (&assembly->guid);
6236         mono_dynamic_stream_reset (&assembly->sheap);
6237
6238         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6239         g_hash_table_destroy (assembly->blob_cache);
6240         assembly->blob_cache = NULL;
6241 }
6242
6243 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6244
6245 void
6246 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6247 {
6248         g_assert_not_reached ();
6249 }
6250
6251 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6252
6253 #ifndef DISABLE_REFLECTION_EMIT
6254
6255 MonoReflectionModule *
6256 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6257 {
6258         char *name;
6259         MonoImage *image;
6260         MonoImageOpenStatus status;
6261         MonoDynamicAssembly *assembly;
6262         guint32 module_count;
6263         MonoImage **new_modules;
6264         gboolean *new_modules_loaded;
6265         
6266         name = mono_string_to_utf8 (fileName);
6267
6268         image = mono_image_open (name, &status);
6269         if (!image) {
6270                 MonoException *exc;
6271                 if (status == MONO_IMAGE_ERROR_ERRNO)
6272                         exc = mono_get_exception_file_not_found (fileName);
6273                 else
6274                         exc = mono_get_exception_bad_image_format (name);
6275                 g_free (name);
6276                 mono_raise_exception (exc);
6277         }
6278
6279         g_free (name);
6280
6281         assembly = ab->dynamic_assembly;
6282         image->assembly = (MonoAssembly*)assembly;
6283
6284         module_count = image->assembly->image->module_count;
6285         new_modules = g_new0 (MonoImage *, module_count + 1);
6286         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6287
6288         if (image->assembly->image->modules)
6289                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6290         if (image->assembly->image->modules_loaded)
6291                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6292         new_modules [module_count] = image;
6293         new_modules_loaded [module_count] = TRUE;
6294         mono_image_addref (image);
6295
6296         g_free (image->assembly->image->modules);
6297         image->assembly->image->modules = new_modules;
6298         image->assembly->image->modules_loaded = new_modules_loaded;
6299         image->assembly->image->module_count ++;
6300
6301         mono_assembly_load_references (image, &status);
6302         if (status) {
6303                 mono_image_close (image);
6304                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6305         }
6306
6307         return mono_module_get_object (mono_domain_get (), image);
6308 }
6309
6310 #endif /* DISABLE_REFLECTION_EMIT */
6311
6312 /*
6313  * We need to return always the same object for MethodInfo, FieldInfo etc..
6314  * but we need to consider the reflected type.
6315  * type uses a different hash, since it uses custom hash/equal functions.
6316  */
6317
6318 typedef struct {
6319         gpointer item;
6320         MonoClass *refclass;
6321 } ReflectedEntry;
6322
6323 static gboolean
6324 reflected_equal (gconstpointer a, gconstpointer b) {
6325         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6326         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6327
6328         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6329 }
6330
6331 static guint
6332 reflected_hash (gconstpointer a) {
6333         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6334         return mono_aligned_addr_hash (ea->item);
6335 }
6336
6337 #define CHECK_OBJECT(t,p,k)     \
6338         do {    \
6339                 t _obj; \
6340                 ReflectedEntry e;       \
6341                 e.item = (p);   \
6342                 e.refclass = (k);       \
6343                 mono_domain_lock (domain);      \
6344                 if (!domain->refobject_hash)    \
6345                         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");  \
6346                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6347                         mono_domain_unlock (domain);    \
6348                         return _obj;    \
6349                 }       \
6350         mono_domain_unlock (domain); \
6351         } while (0)
6352
6353 #ifdef HAVE_BOEHM_GC
6354 /* ReflectedEntry doesn't need to be GC tracked */
6355 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6356 #define FREE_REFENTRY(entry) g_free ((entry))
6357 #define REFENTRY_REQUIRES_CLEANUP
6358 #else
6359 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6360 /* FIXME: */
6361 #define FREE_REFENTRY(entry)
6362 #endif
6363
6364 #define CACHE_OBJECT(t,p,o,k)   \
6365         do {    \
6366                 t _obj; \
6367         ReflectedEntry pe; \
6368         pe.item = (p); \
6369         pe.refclass = (k); \
6370         mono_domain_lock (domain); \
6371                 if (!domain->refobject_hash)    \
6372                         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");  \
6373         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6374         if (!_obj) { \
6375                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6376                     e->item = (p);      \
6377                     e->refclass = (k);  \
6378                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6379             _obj = o; \
6380         } \
6381                 mono_domain_unlock (domain);    \
6382         return _obj; \
6383         } while (0)
6384
6385 static void
6386 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6387 {
6388         mono_domain_lock (domain);
6389         if (domain->refobject_hash) {
6390         ReflectedEntry pe;
6391                 gpointer orig_pe, orig_value;
6392
6393                 pe.item = o;
6394                 pe.refclass = klass;
6395                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6396                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6397                         FREE_REFENTRY (orig_pe);
6398                 }
6399         }
6400         mono_domain_unlock (domain);
6401 }
6402
6403 #ifdef REFENTRY_REQUIRES_CLEANUP
6404 static void
6405 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6406 {
6407         FREE_REFENTRY (key);
6408 }
6409 #endif
6410
6411 void
6412 mono_reflection_cleanup_domain (MonoDomain *domain)
6413 {
6414         if (domain->refobject_hash) {
6415 /*let's avoid scanning the whole hashtable if not needed*/
6416 #ifdef REFENTRY_REQUIRES_CLEANUP
6417                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6418 #endif
6419                 mono_g_hash_table_destroy (domain->refobject_hash);
6420                 domain->refobject_hash = NULL;
6421         }
6422 }
6423
6424 #ifndef DISABLE_REFLECTION_EMIT
6425 static gpointer
6426 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6427 {
6428         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6429 }
6430
6431 static gpointer
6432 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6433 {
6434         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6435 }
6436
6437 void
6438 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6439 {
6440         MonoDynamicImage *image = moduleb->dynamic_image;
6441         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6442         if (!image) {
6443                 MonoError error;
6444                 int module_count;
6445                 MonoImage **new_modules;
6446                 MonoImage *ass;
6447                 char *name, *fqname;
6448                 /*
6449                  * FIXME: we already created an image in mono_image_basic_init (), but
6450                  * we don't know which module it belongs to, since that is only 
6451                  * determined at assembly save time.
6452                  */
6453                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6454                 name = mono_string_to_utf8 (ab->name);
6455                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6456                 if (!mono_error_ok (&error)) {
6457                         g_free (name);
6458                         mono_error_raise_exception (&error);
6459                 }
6460                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6461
6462                 moduleb->module.image = &image->image;
6463                 moduleb->dynamic_image = image;
6464                 register_module (mono_object_domain (moduleb), moduleb, image);
6465
6466                 /* register the module with the assembly */
6467                 ass = ab->dynamic_assembly->assembly.image;
6468                 module_count = ass->module_count;
6469                 new_modules = g_new0 (MonoImage *, module_count + 1);
6470
6471                 if (ass->modules)
6472                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6473                 new_modules [module_count] = &image->image;
6474                 mono_image_addref (&image->image);
6475
6476                 g_free (ass->modules);
6477                 ass->modules = new_modules;
6478                 ass->module_count ++;
6479         }
6480 }
6481
6482 void
6483 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6484 {
6485         MonoDynamicImage *image = moduleb->dynamic_image;
6486
6487         g_assert (type->type);
6488         image->wrappers_type = mono_class_from_mono_type (type->type);
6489 }
6490
6491 #endif
6492
6493 /*
6494  * mono_assembly_get_object:
6495  * @domain: an app domain
6496  * @assembly: an assembly
6497  *
6498  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6499  */
6500 MonoReflectionAssembly*
6501 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6502 {
6503         MonoError error;
6504         static MonoClass *assembly_type;
6505         MonoReflectionAssembly *res;
6506         
6507         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6508         if (!assembly_type) {
6509                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6510                 if (klass == NULL)
6511                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6512                 g_assert (klass);
6513                 assembly_type = klass;
6514         }
6515         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6516         mono_error_raise_exception (&error); /* FIXME don't raise here */
6517         res->assembly = assembly;
6518
6519         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6520 }
6521
6522
6523
6524 MonoReflectionModule*   
6525 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6526 {
6527         MonoError error;
6528         static MonoClass *module_type;
6529         MonoReflectionModule *res;
6530         char* basename;
6531         
6532         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6533         if (!module_type) {
6534                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6535                 if (klass == NULL)
6536                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6537                 g_assert (klass);
6538                 module_type = klass;
6539         }
6540         res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6541         mono_error_raise_exception (&error); /* FIXME don't raise here */
6542
6543         res->image = image;
6544         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6545
6546         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6547         basename = g_path_get_basename (image->name);
6548         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6549         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6550         
6551         g_free (basename);
6552
6553         if (image->assembly->image == image) {
6554                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6555         } else {
6556                 int i;
6557                 res->token = 0;
6558                 if (image->assembly->image->modules) {
6559                         for (i = 0; i < image->assembly->image->module_count; i++) {
6560                                 if (image->assembly->image->modules [i] == image)
6561                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6562                         }
6563                         g_assert (res->token);
6564                 }
6565         }
6566
6567         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6568 }
6569
6570 MonoReflectionModule*   
6571 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6572 {
6573         MonoError error;
6574         static MonoClass *module_type;
6575         MonoReflectionModule *res;
6576         MonoTableInfo *table;
6577         guint32 cols [MONO_FILE_SIZE];
6578         const char *name;
6579         guint32 i, name_idx;
6580         const char *val;
6581         
6582         if (!module_type) {
6583                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6584                 if (klass == NULL)
6585                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6586                 g_assert (klass);
6587                 module_type = klass;
6588         }
6589         res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6590         mono_error_raise_exception (&error); /* FIXME don't raise here */
6591
6592         table = &image->tables [MONO_TABLE_FILE];
6593         g_assert (table_index < table->rows);
6594         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6595
6596         res->image = NULL;
6597         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6598         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6599
6600         /* Check whenever the row has a corresponding row in the moduleref table */
6601         table = &image->tables [MONO_TABLE_MODULEREF];
6602         for (i = 0; i < table->rows; ++i) {
6603                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6604                 val = mono_metadata_string_heap (image, name_idx);
6605                 if (strcmp (val, name) == 0)
6606                         res->image = image->modules [i];
6607         }
6608
6609         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6610         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6611         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6612         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6613         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6614
6615         return res;
6616 }
6617
6618 static gboolean
6619 verify_safe_for_managed_space (MonoType *type)
6620 {
6621         switch (type->type) {
6622 #ifdef DEBUG_HARDER
6623         case MONO_TYPE_ARRAY:
6624                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6625         case MONO_TYPE_PTR:
6626                 return verify_safe_for_managed_space (type->data.type);
6627         case MONO_TYPE_SZARRAY:
6628                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6629         case MONO_TYPE_GENERICINST: {
6630                 MonoGenericInst *inst = type->data.generic_class->inst;
6631                 int i;
6632                 if (!inst->is_open)
6633                         break;
6634                 for (i = 0; i < inst->type_argc; ++i)
6635                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6636                                 return FALSE;
6637                 return TRUE;
6638         }
6639 #endif
6640         case MONO_TYPE_VAR:
6641         case MONO_TYPE_MVAR:
6642                 return TRUE;
6643         default:
6644                 return TRUE;
6645         }
6646 }
6647
6648 static MonoType*
6649 mono_type_normalize (MonoType *type)
6650 {
6651         int i;
6652         MonoGenericClass *gclass;
6653         MonoGenericInst *ginst;
6654         MonoClass *gtd;
6655         MonoGenericContainer *gcontainer;
6656         MonoType **argv = NULL;
6657         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6658
6659         if (type->type != MONO_TYPE_GENERICINST)
6660                 return type;
6661
6662         gclass = type->data.generic_class;
6663         ginst = gclass->context.class_inst;
6664         if (!ginst->is_open)
6665                 return type;
6666
6667         gtd = gclass->container_class;
6668         gcontainer = gtd->generic_container;
6669         argv = g_newa (MonoType*, ginst->type_argc);
6670
6671         for (i = 0; i < ginst->type_argc; ++i) {
6672                 MonoType *t = ginst->type_argv [i], *norm;
6673                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6674                         is_denorm_gtd = FALSE;
6675                 norm = mono_type_normalize (t);
6676                 argv [i] = norm;
6677                 if (norm != t)
6678                         requires_rebind = TRUE;
6679         }
6680
6681         if (is_denorm_gtd)
6682                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6683
6684         if (requires_rebind) {
6685                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6686                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6687         }
6688
6689         return type;
6690 }
6691 /*
6692  * mono_type_get_object:
6693  * @domain: an app domain
6694  * @type: a type
6695  *
6696  * Return an System.MonoType object representing the type @type.
6697  */
6698 MonoReflectionType*
6699 mono_type_get_object (MonoDomain *domain, MonoType *type)
6700 {
6701         MonoError error;
6702         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6703         mono_error_raise_exception (&error);
6704
6705         return ret;
6706 }
6707
6708 MonoReflectionType*
6709 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6710 {
6711         MonoType *norm_type;
6712         MonoReflectionType *res;
6713         MonoClass *klass;
6714
6715         mono_error_init (error);
6716
6717         klass = mono_class_from_mono_type (type);
6718
6719         /*we must avoid using @type as it might have come
6720          * from a mono_metadata_type_dup and the caller
6721          * expects that is can be freed.
6722          * Using the right type from 
6723          */
6724         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6725
6726         /* void is very common */
6727         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6728                 return (MonoReflectionType*)domain->typeof_void;
6729
6730         /*
6731          * If the vtable of the given class was already created, we can use
6732          * the MonoType from there and avoid all locking and hash table lookups.
6733          * 
6734          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6735          * that the resulting object is different.   
6736          */
6737         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6738                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6739                 if (vtable && vtable->type)
6740                         return (MonoReflectionType *)vtable->type;
6741         }
6742
6743         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6744         mono_domain_lock (domain);
6745         if (!domain->type_hash)
6746                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6747                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6748         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6749                 mono_domain_unlock (domain);
6750                 mono_loader_unlock ();
6751                 return res;
6752         }
6753
6754         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6755          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6756          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6757          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6758          * artifact of how generics are encoded and should be transparent to managed code so we
6759          * need to weed out this diference when retrieving managed System.Type objects.
6760          */
6761         norm_type = mono_type_normalize (type);
6762         if (norm_type != type) {
6763                 res = mono_type_get_object_checked (domain, norm_type, error);
6764                 if (!mono_error_ok (error))
6765                         return NULL;
6766                 mono_g_hash_table_insert (domain->type_hash, type, res);
6767                 mono_domain_unlock (domain);
6768                 mono_loader_unlock ();
6769                 return res;
6770         }
6771
6772         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6773         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6774                 g_assert (0);
6775
6776         if (!verify_safe_for_managed_space (type)) {
6777                 mono_domain_unlock (domain);
6778                 mono_loader_unlock ();
6779                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6780         }
6781
6782         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6783                 gboolean is_type_done = TRUE;
6784                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6785                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6786                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6787                 */
6788                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6789                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6790
6791                         if (gparam->owner && gparam->owner->is_method) {
6792                                 MonoMethod *method = gparam->owner->owner.method;
6793                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6794                                         is_type_done = FALSE;
6795                         } else if (gparam->owner && !gparam->owner->is_method) {
6796                                 MonoClass *klass = gparam->owner->owner.klass;
6797                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6798                                         is_type_done = FALSE;
6799                         }
6800                 } 
6801
6802                 /* g_assert_not_reached (); */
6803                 /* should this be considered an error condition? */
6804                 if (is_type_done && !type->byref) {
6805                         mono_domain_unlock (domain);
6806                         mono_loader_unlock ();
6807                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
6808                 }
6809         }
6810         /* This is stored in vtables/JITted code so it has to be pinned */
6811         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6812         if (!mono_error_ok (error))
6813                 return NULL;
6814
6815         res->type = type;
6816         mono_g_hash_table_insert (domain->type_hash, type, res);
6817
6818         if (type->type == MONO_TYPE_VOID)
6819                 domain->typeof_void = (MonoObject*)res;
6820
6821         mono_domain_unlock (domain);
6822         mono_loader_unlock ();
6823         return res;
6824 }
6825
6826 /*
6827  * mono_method_get_object:
6828  * @domain: an app domain
6829  * @method: a method
6830  * @refclass: the reflected type (can be NULL)
6831  *
6832  * Return an System.Reflection.MonoMethod object representing the method @method.
6833  */
6834 MonoReflectionMethod*
6835 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6836 {
6837         MonoError error;
6838         MonoReflectionMethod *ret = NULL;
6839         ret = mono_method_get_object_checked (domain, method, refclass, &error);
6840         mono_error_raise_exception (&error);
6841         return ret;
6842 }
6843
6844 /*
6845  * mono_method_get_object_checked:
6846  * @domain: an app domain
6847  * @method: a method
6848  * @refclass: the reflected type (can be NULL)
6849  * @error: set on error.
6850  *
6851  * Return an System.Reflection.MonoMethod object representing the method @method.
6852  * Returns NULL and sets @error on error.
6853  */
6854 MonoReflectionMethod*
6855 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
6856 {
6857         /*
6858          * We use the same C representation for methods and constructors, but the type 
6859          * name in C# is different.
6860          */
6861         static MonoClass *System_Reflection_MonoMethod = NULL;
6862         static MonoClass *System_Reflection_MonoCMethod = NULL;
6863         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6864         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6865         MonoReflectionType *rt;
6866         MonoClass *klass;
6867         MonoReflectionMethod *ret;
6868
6869         mono_error_init (error);
6870
6871         if (method->is_inflated) {
6872                 MonoReflectionGenericMethod *gret;
6873
6874                 if (!refclass)
6875                         refclass = method->klass;
6876                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6877                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6878                         if (!System_Reflection_MonoGenericCMethod) {
6879                                 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
6880                                 if (!mono_error_ok (error))
6881                                         goto leave;
6882                         }
6883                         klass = System_Reflection_MonoGenericCMethod;
6884                 } else {
6885                         if (!System_Reflection_MonoGenericMethod) {
6886                                 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
6887                                 if (!mono_error_ok (error))
6888                                         goto leave;
6889                         }
6890                         klass = System_Reflection_MonoGenericMethod;
6891                 }
6892                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
6893                 if (!mono_error_ok (error))
6894                         goto leave;
6895                 gret->method.method = method;
6896
6897                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6898
6899                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
6900                 if (!mono_error_ok (error))
6901                     goto leave;
6902
6903                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
6904
6905                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6906         }
6907
6908         if (!refclass)
6909                 refclass = method->klass;
6910
6911         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6912         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6913                 if (!System_Reflection_MonoCMethod) {
6914                         System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
6915                         if (!mono_error_ok (error))
6916                                 goto leave;
6917                 }
6918                 klass = System_Reflection_MonoCMethod;
6919         }
6920         else {
6921                 if (!System_Reflection_MonoMethod) {
6922                         System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
6923                         if (!mono_error_ok (error))
6924                                 goto leave;
6925                 }
6926                 klass = System_Reflection_MonoMethod;
6927         }
6928         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
6929         if (!mono_error_ok (error))
6930                 goto leave;
6931         ret->method = method;
6932
6933         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
6934         if (!mono_error_ok (error))
6935                 goto leave;
6936
6937         MONO_OBJECT_SETREF (ret, reftype, rt);
6938
6939         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6940
6941 leave:
6942         g_assert (!mono_error_ok (error));
6943         return NULL;
6944 }
6945
6946 /*
6947  * mono_method_clear_object:
6948  *
6949  *   Clear the cached reflection objects for the dynamic method METHOD.
6950  */
6951 void
6952 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6953 {
6954         MonoClass *klass;
6955         g_assert (method_is_dynamic (method));
6956
6957         klass = method->klass;
6958         while (klass) {
6959                 clear_cached_object (domain, method, klass);
6960                 klass = klass->parent;
6961         }
6962         /* Added by mono_param_get_objects () */
6963         clear_cached_object (domain, &(method->signature), NULL);
6964         klass = method->klass;
6965         while (klass) {
6966                 clear_cached_object (domain, &(method->signature), klass);
6967                 klass = klass->parent;
6968         }
6969 }
6970
6971 /*
6972  * mono_field_get_object:
6973  * @domain: an app domain
6974  * @klass: a type
6975  * @field: a field
6976  *
6977  * Return an System.Reflection.MonoField object representing the field @field
6978  * in class @klass.
6979  */
6980 MonoReflectionField*
6981 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6982 {
6983         MonoError error;
6984         MonoReflectionField *result;
6985         result = mono_field_get_object_checked (domain, klass, field, &error);
6986         mono_error_raise_exception (&error);
6987         return result;
6988 }
6989
6990 /*
6991  * mono_field_get_object_checked:
6992  * @domain: an app domain
6993  * @klass: a type
6994  * @field: a field
6995  * @error: set on error
6996  *
6997  * Return an System.Reflection.MonoField object representing the field @field
6998  * in class @klass. On error, returns NULL and sets @error.
6999  */
7000 MonoReflectionField*
7001 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7002 {
7003         MonoReflectionType *rt;
7004         MonoReflectionField *res;
7005         static MonoClass *monofield_klass;
7006
7007         mono_error_init (error);
7008
7009         CHECK_OBJECT (MonoReflectionField *, field, klass);
7010         if (!monofield_klass)
7011                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7012         res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7013         mono_error_raise_exception (error); /* FIXME don't raise here */
7014         res->klass = klass;
7015         res->field = field;
7016         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7017
7018         if (is_field_on_inst (field)) {
7019                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7020
7021                 rt = mono_type_get_object_checked (domain, field->type, error);
7022                 if (!mono_error_ok (error))
7023                         return NULL;
7024
7025                 MONO_OBJECT_SETREF (res, type, rt);
7026         } else {
7027                 if (field->type) {
7028                         rt = mono_type_get_object_checked (domain, field->type, error);
7029                         if (!mono_error_ok (error))
7030                                 return NULL;
7031
7032                         MONO_OBJECT_SETREF (res, type, rt);
7033                 }
7034                 res->attrs = mono_field_get_flags (field);
7035         }
7036         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7037 }
7038
7039 /*
7040  * mono_property_get_object:
7041  * @domain: an app domain
7042  * @klass: a type
7043  * @property: a property
7044  *
7045  * Return an System.Reflection.MonoProperty object representing the property @property
7046  * in class @klass.
7047  */
7048 MonoReflectionProperty*
7049 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7050 {
7051         MonoError error;
7052         MonoReflectionProperty *res;
7053         static MonoClass *monoproperty_klass;
7054
7055         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7056         if (!monoproperty_klass)
7057                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7058         res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7059         mono_error_raise_exception (&error); /* FIXME don't raise here */
7060         res->klass = klass;
7061         res->property = property;
7062         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7063 }
7064
7065 /*
7066  * mono_event_get_object:
7067  * @domain: an app domain
7068  * @klass: a type
7069  * @event: a event
7070  *
7071  * Return an System.Reflection.MonoEvent object representing the event @event
7072  * in class @klass.
7073  */
7074 MonoReflectionEvent*
7075 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7076 {
7077         MonoError error;
7078         MonoReflectionEvent *res;
7079         MonoReflectionMonoEvent *mono_event;
7080         static MonoClass *monoevent_klass;
7081
7082         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7083         if (!monoevent_klass)
7084                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7085         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7086         mono_error_raise_exception (&error); /* FIXME don't raise here */
7087         mono_event->klass = klass;
7088         mono_event->event = event;
7089         res = (MonoReflectionEvent*)mono_event;
7090         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7091 }
7092
7093 /**
7094  * mono_get_reflection_missing_object:
7095  * @domain: Domain where the object lives
7096  *
7097  * Returns the System.Reflection.Missing.Value singleton object
7098  * (of type System.Reflection.Missing).
7099  *
7100  * Used as the value for ParameterInfo.DefaultValue when Optional
7101  * is present
7102  */
7103 static MonoObject *
7104 mono_get_reflection_missing_object (MonoDomain *domain)
7105 {
7106         MonoObject *obj;
7107         static MonoClassField *missing_value_field = NULL;
7108         
7109         if (!missing_value_field) {
7110                 MonoClass *missing_klass;
7111                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7112                 mono_class_init (missing_klass);
7113                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7114                 g_assert (missing_value_field);
7115         }
7116         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7117         g_assert (obj);
7118         return obj;
7119 }
7120
7121 static MonoObject*
7122 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7123 {
7124         if (!*dbnull)
7125                 *dbnull = mono_get_dbnull_object (domain);
7126         return *dbnull;
7127 }
7128
7129 static MonoObject*
7130 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7131 {
7132         if (!*reflection_missing)
7133                 *reflection_missing = mono_get_reflection_missing_object (domain);
7134         return *reflection_missing;
7135 }
7136
7137 /*
7138  * mono_param_get_objects:
7139  * @domain: an app domain
7140  * @method: a method
7141  *
7142  * Return an System.Reflection.ParameterInfo array object representing the parameters
7143  * in the method @method.
7144  */
7145 MonoArray*
7146 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7147 {
7148         static MonoClass *System_Reflection_ParameterInfo;
7149         static MonoClass *System_Reflection_ParameterInfo_array;
7150         MonoError error;
7151         MonoArray *res = NULL;
7152         MonoReflectionMethod *member = NULL;
7153         MonoReflectionParameter *param = NULL;
7154         char **names, **blobs = NULL;
7155         guint32 *types = NULL;
7156         MonoType *type = NULL;
7157         MonoObject *dbnull = NULL;
7158         MonoObject *missing = NULL;
7159         MonoMarshalSpec **mspecs;
7160         MonoMethodSignature *sig;
7161         MonoVTable *pinfo_vtable;
7162         MonoReflectionType *rt;
7163         int i;
7164
7165         if (!System_Reflection_ParameterInfo_array) {
7166                 MonoClass *klass;
7167
7168                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7169                 if (!klass)
7170                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7171
7172                 mono_memory_barrier ();
7173                 System_Reflection_ParameterInfo = klass; 
7174
7175         
7176                 klass = mono_array_class_get (klass, 1);
7177                 mono_memory_barrier ();
7178                 System_Reflection_ParameterInfo_array = klass;
7179         }
7180
7181         sig = mono_method_signature_checked (method, &error);
7182         if (!mono_error_ok (&error))
7183                 mono_error_raise_exception (&error);
7184
7185         if (!sig->param_count) {
7186                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7187                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7188
7189                 return res;
7190         }
7191
7192         /* Note: the cache is based on the address of the signature into the method
7193          * since we already cache MethodInfos with the method as keys.
7194          */
7195         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7196
7197         member = mono_method_get_object_checked (domain, method, refclass, &error);
7198         mono_error_raise_exception (&error); /* FIXME don't raise here */
7199         names = g_new (char *, sig->param_count);
7200         mono_method_get_param_names (method, (const char **) names);
7201
7202         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7203         mono_method_get_marshal_info (method, mspecs);
7204
7205         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7206         mono_error_raise_exception (&error); /* FIXME don't raise here */
7207
7208         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7209         for (i = 0; i < sig->param_count; ++i) {
7210                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7211                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7212
7213                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7214                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7215
7216                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7217
7218                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7219
7220                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7221
7222                 param->PositionImpl = i;
7223                 param->AttrsImpl = sig->params [i]->attrs;
7224
7225                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7226                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7227                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7228                         else
7229                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7230                 } else {
7231
7232                         if (!blobs) {
7233                                 blobs = g_new0 (char *, sig->param_count);
7234                                 types = g_new0 (guint32, sig->param_count);
7235                                 get_default_param_value_blobs (method, blobs, types); 
7236                         }
7237
7238                         /* Build MonoType for the type from the Constant Table */
7239                         if (!type)
7240                                 type = g_new0 (MonoType, 1);
7241                         type->type = (MonoTypeEnum)types [i];
7242                         type->data.klass = NULL;
7243                         if (types [i] == MONO_TYPE_CLASS)
7244                                 type->data.klass = mono_defaults.object_class;
7245                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7246                                 /* For enums, types [i] contains the base type */
7247
7248                                         type->type = MONO_TYPE_VALUETYPE;
7249                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7250                         } else
7251                                 type->data.klass = mono_class_from_mono_type (type);
7252
7253                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7254
7255                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7256                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7257                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7258                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7259                                 else
7260                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7261                         }
7262                         
7263                 }
7264
7265                 if (mspecs [i + 1])
7266                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7267                 
7268                 mono_array_setref (res, i, param);
7269         }
7270         g_free (names);
7271         g_free (blobs);
7272         g_free (types);
7273         g_free (type);
7274
7275         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7276                 if (mspecs [i])
7277                         mono_metadata_free_marshal_spec (mspecs [i]);
7278         g_free (mspecs);
7279         
7280         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7281 }
7282
7283 MonoArray*
7284 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7285 {
7286         return mono_param_get_objects_internal (domain, method, NULL);
7287 }
7288
7289 /*
7290  * mono_method_body_get_object:
7291  * @domain: an app domain
7292  * @method: a method
7293  *
7294  * Return an System.Reflection.MethodBody object representing the method @method.
7295  */
7296 MonoReflectionMethodBody*
7297 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7298 {
7299         static MonoClass *System_Reflection_MethodBody = NULL;
7300         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7301         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7302         MonoError error;
7303         MonoReflectionMethodBody *ret;
7304         MonoMethodHeader *header;
7305         MonoImage *image;
7306         MonoReflectionType *rt;
7307         guint32 method_rva, local_var_sig_token;
7308     char *ptr;
7309         unsigned char format, flags;
7310         int i;
7311
7312         /* for compatibility with .net */
7313     if (method_is_dynamic (method))
7314         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7315
7316         if (!System_Reflection_MethodBody)
7317                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7318         if (!System_Reflection_LocalVariableInfo)
7319                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7320         if (!System_Reflection_ExceptionHandlingClause)
7321                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7322
7323         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7324
7325         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7326                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7327             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7328                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7329             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7330                 return NULL;
7331
7332         image = method->klass->image;
7333         header = mono_method_get_header (method);
7334
7335         if (!image_is_dynamic (image)) {
7336                 /* Obtain local vars signature token */
7337                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7338                 ptr = mono_image_rva_map (image, method_rva);
7339                 flags = *(const unsigned char *) ptr;
7340                 format = flags & METHOD_HEADER_FORMAT_MASK;
7341                 switch (format){
7342                 case METHOD_HEADER_TINY_FORMAT:
7343                         local_var_sig_token = 0;
7344                         break;
7345                 case METHOD_HEADER_FAT_FORMAT:
7346                         ptr += 2;
7347                         ptr += 2;
7348                         ptr += 4;
7349                         local_var_sig_token = read32 (ptr);
7350                         break;
7351                 default:
7352                         g_assert_not_reached ();
7353                 }
7354         } else
7355                 local_var_sig_token = 0; //FIXME
7356
7357         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7358         mono_error_raise_exception (&error); /* FIXME don't raise here */
7359
7360         ret->init_locals = header->init_locals;
7361         ret->max_stack = header->max_stack;
7362         ret->local_var_sig_token = local_var_sig_token;
7363         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7364         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7365
7366         /* Locals */
7367         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7368         for (i = 0; i < header->num_locals; ++i) {
7369                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7370                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7371
7372                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7373                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7374
7375                 MONO_OBJECT_SETREF (info, local_type, rt);
7376
7377                 info->is_pinned = header->locals [i]->pinned;
7378                 info->local_index = i;
7379                 mono_array_setref (ret->locals, i, info);
7380         }
7381
7382         /* Exceptions */
7383         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7384         for (i = 0; i < header->num_clauses; ++i) {
7385                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7386                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7387                 MonoExceptionClause *clause = &header->clauses [i];
7388
7389                 info->flags = clause->flags;
7390                 info->try_offset = clause->try_offset;
7391                 info->try_length = clause->try_len;
7392                 info->handler_offset = clause->handler_offset;
7393                 info->handler_length = clause->handler_len;
7394                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7395                         info->filter_offset = clause->data.filter_offset;
7396                 else if (clause->data.catch_class) {
7397                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7398                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7399
7400                         MONO_OBJECT_SETREF (info, catch_type, rt);
7401                 }
7402
7403                 mono_array_setref (ret->clauses, i, info);
7404         }
7405
7406         mono_metadata_free_mh (header);
7407         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7408         return ret;
7409 }
7410
7411 /**
7412  * mono_get_dbnull_object:
7413  * @domain: Domain where the object lives
7414  *
7415  * Returns the System.DBNull.Value singleton object
7416  *
7417  * Used as the value for ParameterInfo.DefaultValue 
7418  */
7419 MonoObject *
7420 mono_get_dbnull_object (MonoDomain *domain)
7421 {
7422         MonoObject *obj;
7423         static MonoClassField *dbnull_value_field = NULL;
7424         
7425         if (!dbnull_value_field) {
7426                 MonoClass *dbnull_klass;
7427                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7428                 mono_class_init (dbnull_klass);
7429                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7430                 g_assert (dbnull_value_field);
7431         }
7432         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7433         g_assert (obj);
7434         return obj;
7435 }
7436
7437 static void
7438 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7439 {
7440         guint32 param_index, i, lastp, crow = 0;
7441         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7442         gint32 idx;
7443
7444         MonoClass *klass = method->klass;
7445         MonoImage *image = klass->image;
7446         MonoMethodSignature *methodsig = mono_method_signature (method);
7447
7448         MonoTableInfo *constt;
7449         MonoTableInfo *methodt;
7450         MonoTableInfo *paramt;
7451
7452         if (!methodsig->param_count)
7453                 return;
7454
7455         mono_class_init (klass);
7456
7457         if (image_is_dynamic (klass->image)) {
7458                 MonoReflectionMethodAux *aux;
7459                 if (method->is_inflated)
7460                         method = ((MonoMethodInflated*)method)->declaring;
7461                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7462                 if (aux && aux->param_defaults) {
7463                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7464                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7465                 }
7466                 return;
7467         }
7468
7469         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7470         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7471         constt = &image->tables [MONO_TABLE_CONSTANT];
7472
7473         idx = mono_method_get_index (method) - 1;
7474         g_assert (idx != -1);
7475
7476         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7477         if (idx + 1 < methodt->rows)
7478                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7479         else
7480                 lastp = paramt->rows + 1;
7481
7482         for (i = param_index; i < lastp; ++i) {
7483                 guint32 paramseq;
7484
7485                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7486                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7487
7488                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7489                         continue;
7490
7491                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7492                 if (!crow) {
7493                         continue;
7494                 }
7495         
7496                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7497                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7498                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7499         }
7500
7501         return;
7502 }
7503
7504 MonoObject *
7505 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7506 {
7507         MonoError error;
7508         void *retval;
7509         MonoClass *klass;
7510         MonoObject *object;
7511         MonoType *basetype = type;
7512
7513         if (!blob)
7514                 return NULL;
7515         
7516         klass = mono_class_from_mono_type (type);
7517         if (klass->valuetype) {
7518                 object = mono_object_new_checked (domain, klass, &error);
7519                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7520                 retval = ((gchar *) object + sizeof (MonoObject));
7521                 if (klass->enumtype)
7522                         basetype = mono_class_enum_basetype (klass);
7523         } else {
7524                 retval = &object;
7525         }
7526                         
7527         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7528                 return object;
7529         else
7530                 return NULL;
7531 }
7532
7533 static int
7534 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7535         int found_sep;
7536         char *s;
7537         gboolean quoted = FALSE;
7538
7539         memset (assembly, 0, sizeof (MonoAssemblyName));
7540         assembly->culture = "";
7541         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7542
7543         if (*p == '"') {
7544                 quoted = TRUE;
7545                 p++;
7546         }
7547         assembly->name = p;
7548         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7549                 p++;
7550         if (quoted) {
7551                 if (*p != '"')
7552                         return 1;
7553                 *p = 0;
7554                 p++;
7555         }
7556         if (*p != ',')
7557                 return 1;
7558         *p = 0;
7559         /* Remove trailing whitespace */
7560         s = p - 1;
7561         while (*s && g_ascii_isspace (*s))
7562                 *s-- = 0;
7563         p ++;
7564         while (g_ascii_isspace (*p))
7565                 p++;
7566         while (*p) {
7567                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7568                         p += 8;
7569                         assembly->major = strtoul (p, &s, 10);
7570                         if (s == p || *s != '.')
7571                                 return 1;
7572                         p = ++s;
7573                         assembly->minor = strtoul (p, &s, 10);
7574                         if (s == p || *s != '.')
7575                                 return 1;
7576                         p = ++s;
7577                         assembly->build = strtoul (p, &s, 10);
7578                         if (s == p || *s != '.')
7579                                 return 1;
7580                         p = ++s;
7581                         assembly->revision = strtoul (p, &s, 10);
7582                         if (s == p)
7583                                 return 1;
7584                         p = s;
7585                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7586                         p += 8;
7587                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7588                                 assembly->culture = "";
7589                                 p += 7;
7590                         } else {
7591                                 assembly->culture = p;
7592                                 while (*p && *p != ',') {
7593                                         p++;
7594                                 }
7595                         }
7596                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7597                         p += 15;
7598                         if (strncmp (p, "null", 4) == 0) {
7599                                 p += 4;
7600                         } else {
7601                                 int len;
7602                                 gchar *start = p;
7603                                 while (*p && *p != ',') {
7604                                         p++;
7605                                 }
7606                                 len = (p - start + 1);
7607                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7608                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7609                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7610                         }
7611                 } else {
7612                         while (*p && *p != ',')
7613                                 p++;
7614                 }
7615                 found_sep = 0;
7616                 while (g_ascii_isspace (*p) || *p == ',') {
7617                         *p++ = 0;
7618                         found_sep = 1;
7619                         continue;
7620                 }
7621                 /* failed */
7622                 if (!found_sep)
7623                         return 1;
7624         }
7625
7626         return 0;
7627 }
7628
7629 /*
7630  * mono_reflection_parse_type:
7631  * @name: type name
7632  *
7633  * Parse a type name as accepted by the GetType () method and output the info
7634  * extracted in the info structure.
7635  * the name param will be mangled, so, make a copy before passing it to this function.
7636  * The fields in info will be valid until the memory pointed to by name is valid.
7637  *
7638  * See also mono_type_get_name () below.
7639  *
7640  * Returns: 0 on parse error.
7641  */
7642 static int
7643 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7644                              MonoTypeNameParse *info)
7645 {
7646         char *start, *p, *w, *last_point, *startn;
7647         int in_modifiers = 0;
7648         int isbyref = 0, rank = 0, isptr = 0;
7649
7650         start = p = w = name;
7651
7652         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7653         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7654         info->name = info->name_space = NULL;
7655         info->nested = NULL;
7656         info->modifiers = NULL;
7657         info->type_arguments = NULL;
7658
7659         /* last_point separates the namespace from the name */
7660         last_point = NULL;
7661         /* Skips spaces */
7662         while (*p == ' ') p++, start++, w++, name++;
7663
7664         while (*p) {
7665                 switch (*p) {
7666                 case '+':
7667                         *p = 0; /* NULL terminate the name */
7668                         startn = p + 1;
7669                         info->nested = g_list_append (info->nested, startn);
7670                         /* we have parsed the nesting namespace + name */
7671                         if (info->name)
7672                                 break;
7673                         if (last_point) {
7674                                 info->name_space = start;
7675                                 *last_point = 0;
7676                                 info->name = last_point + 1;
7677                         } else {
7678                                 info->name_space = (char *)"";
7679                                 info->name = start;
7680                         }
7681                         break;
7682                 case '.':
7683                         last_point = p;
7684                         break;
7685                 case '\\':
7686                         ++p;
7687                         break;
7688                 case '&':
7689                 case '*':
7690                 case '[':
7691                 case ',':
7692                 case ']':
7693                         in_modifiers = 1;
7694                         break;
7695                 default:
7696                         break;
7697                 }
7698                 if (in_modifiers)
7699                         break;
7700                 // *w++ = *p++;
7701                 p++;
7702         }
7703         
7704         if (!info->name) {
7705                 if (last_point) {
7706                         info->name_space = start;
7707                         *last_point = 0;
7708                         info->name = last_point + 1;
7709                 } else {
7710                         info->name_space = (char *)"";
7711                         info->name = start;
7712                 }
7713         }
7714         while (*p) {
7715                 switch (*p) {
7716                 case '&':
7717                         if (isbyref) /* only one level allowed by the spec */
7718                                 return 0;
7719                         isbyref = 1;
7720                         isptr = 0;
7721                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7722                         *p++ = 0;
7723                         break;
7724                 case '*':
7725                         if (isbyref) /* pointer to ref not okay */
7726                                 return 0;
7727                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7728                         isptr = 1;
7729                         *p++ = 0;
7730                         break;
7731                 case '[':
7732                         if (isbyref) /* array of ref and generic ref are not okay */
7733                                 return 0;
7734                         //Decide if it's an array of a generic argument list
7735                         *p++ = 0;
7736
7737                         if (!*p) //XXX test
7738                                 return 0;
7739                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7740                                 isptr = 0;
7741                                 rank = 1;
7742                                 while (*p) {
7743                                         if (*p == ']')
7744                                                 break;
7745                                         if (*p == ',')
7746                                                 rank++;
7747                                         else if (*p == '*') /* '*' means unknown lower bound */
7748                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7749                                         else
7750                                                 return 0;
7751                                         ++p;
7752                                 }
7753                                 if (*p++ != ']')
7754                                         return 0;
7755                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7756                         } else {
7757                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7758                                         return 0;
7759                                 isptr = 0;
7760                                 info->type_arguments = g_ptr_array_new ();
7761                                 while (*p) {
7762                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7763                                         gboolean fqname = FALSE;
7764
7765                                         g_ptr_array_add (info->type_arguments, subinfo);
7766
7767                                         while (*p == ' ') p++;
7768                                         if (*p == '[') {
7769                                                 p++;
7770                                                 fqname = TRUE;
7771                                         }
7772
7773                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7774                                                 return 0;
7775
7776                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7777                                         if (fqname && (*p != ']')) {
7778                                                 char *aname;
7779
7780                                                 if (*p != ',')
7781                                                         return 0;
7782                                                 *p++ = 0;
7783
7784                                                 aname = p;
7785                                                 while (*p && (*p != ']'))
7786                                                         p++;
7787
7788                                                 if (*p != ']')
7789                                                         return 0;
7790
7791                                                 *p++ = 0;
7792                                                 while (*aname) {
7793                                                         if (g_ascii_isspace (*aname)) {
7794                                                                 ++aname;
7795                                                                 continue;
7796                                                         }
7797                                                         break;
7798                                                 }
7799                                                 if (!*aname ||
7800                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7801                                                         return 0;
7802                                         } else if (fqname && (*p == ']')) {
7803                                                 *p++ = 0;
7804                                         }
7805                                         if (*p == ']') {
7806                                                 *p++ = 0;
7807                                                 break;
7808                                         } else if (!*p) {
7809                                                 return 0;
7810                                         }
7811                                         *p++ = 0;
7812                                 }
7813                         }
7814                         break;
7815                 case ']':
7816                         if (is_recursed)
7817                                 goto end;
7818                         return 0;
7819                 case ',':
7820                         if (is_recursed)
7821                                 goto end;
7822                         *p++ = 0;
7823                         while (*p) {
7824                                 if (g_ascii_isspace (*p)) {
7825                                         ++p;
7826                                         continue;
7827                                 }
7828                                 break;
7829                         }
7830                         if (!*p)
7831                                 return 0; /* missing assembly name */
7832                         if (!assembly_name_to_aname (&info->assembly, p))
7833                                 return 0;
7834                         break;
7835                 default:
7836                         return 0;
7837                 }
7838                 if (info->assembly.name)
7839                         break;
7840         }
7841         // *w = 0; /* terminate class name */
7842  end:
7843         if (!info->name || !*info->name)
7844                 return 0;
7845         if (endptr)
7846                 *endptr = p;
7847         /* add other consistency checks */
7848         return 1;
7849 }
7850
7851
7852 /**
7853  * mono_identifier_unescape_type_name_chars:
7854  * @identifier: the display name of a mono type
7855  *
7856  * Returns:
7857  *  The name in internal form, that is without escaping backslashes.
7858  *
7859  *  The string is modified in place!
7860  */
7861 char*
7862 mono_identifier_unescape_type_name_chars(char* identifier)
7863 {
7864         char *w, *r;
7865         if (!identifier)
7866                 return NULL;
7867         for (w = r = identifier; *r != 0; r++)
7868         {
7869                 char c = *r;
7870                 if (c == '\\') {
7871                         r++;
7872                         if (*r == 0)
7873                                 break;
7874                         c = *r;
7875                 }
7876                 *w = c;
7877                 w++;
7878         }
7879         if (w != r)
7880                 *w = 0;
7881         return identifier;
7882 }
7883
7884 void
7885 mono_identifier_unescape_info (MonoTypeNameParse* info);
7886
7887 static void
7888 unescape_each_type_argument(void* data, void* user_data)
7889 {
7890         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7891         mono_identifier_unescape_info (info);
7892 }
7893
7894 static void
7895 unescape_each_nested_name (void* data, void* user_data)
7896 {
7897         char* nested_name = (char*) data;
7898         mono_identifier_unescape_type_name_chars(nested_name);
7899 }
7900
7901 /**
7902  * mono_identifier_unescape_info:
7903  *
7904  * @info: a parsed display form of an (optionally assembly qualified) full type name.
7905  *
7906  * Returns: nothing.
7907  *
7908  * Destructively updates the info by unescaping the identifiers that
7909  * comprise the type namespace, name, nested types (if any) and
7910  * generic type arguments (if any).
7911  *
7912  * The resulting info has the names in internal form.
7913  *
7914  */
7915 void
7916 mono_identifier_unescape_info (MonoTypeNameParse *info)
7917 {
7918         if (!info)
7919                 return;
7920         mono_identifier_unescape_type_name_chars(info->name_space);
7921         mono_identifier_unescape_type_name_chars(info->name);
7922         // but don't escape info->assembly
7923         if (info->type_arguments)
7924                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7925         if (info->nested)
7926                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7927 }
7928
7929 int
7930 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7931 {
7932         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7933         if (ok) {
7934                 mono_identifier_unescape_info (info);
7935         }
7936         return ok;
7937 }
7938
7939 static MonoType*
7940 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7941 {
7942         gboolean type_resolve = FALSE;
7943         MonoType *type;
7944         MonoImage *rootimage = image;
7945
7946         if (info->assembly.name) {
7947                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7948                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7949                         /* 
7950                          * This could happen in the AOT compiler case when the search hook is not
7951                          * installed.
7952                          */
7953                         assembly = image->assembly;
7954                 if (!assembly) {
7955                         /* then we must load the assembly ourselve - see #60439 */
7956                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7957                         if (!assembly)
7958                                 return NULL;
7959                 }
7960                 image = assembly->image;
7961         } else if (!image) {
7962                 image = mono_defaults.corlib;
7963         }
7964
7965         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7966         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7967                 image = mono_defaults.corlib;
7968                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7969         }
7970
7971         return type;
7972 }
7973
7974 static MonoType*
7975 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7976 {
7977         MonoError error;
7978         MonoClass *klass;
7979         GList *mod;
7980         int modval;
7981         gboolean bounded = FALSE;
7982         
7983         if (!image)
7984                 image = mono_defaults.corlib;
7985
7986         if (!rootimage)
7987                 rootimage = mono_defaults.corlib;
7988
7989         if (ignorecase) {
7990                 MonoError error;
7991                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7992                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7993         } else {
7994                 klass = mono_class_from_name (image, info->name_space, info->name);
7995         }
7996         if (!klass)
7997                 return NULL;
7998         for (mod = info->nested; mod; mod = mod->next) {
7999                 gpointer iter = NULL;
8000                 MonoClass *parent;
8001
8002                 parent = klass;
8003                 mono_class_init (parent);
8004
8005                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8006                         char *lastp;
8007                         char *nested_name, *nested_nspace;
8008                         gboolean match = TRUE;
8009
8010                         lastp = strrchr ((const char *)mod->data, '.');
8011                         if (lastp) {
8012                                 /* Nested classes can have namespaces */
8013                                 int nspace_len;
8014
8015                                 nested_name = g_strdup (lastp + 1);
8016                                 nspace_len = lastp - (char*)mod->data;
8017                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8018                                 memcpy (nested_nspace, mod->data, nspace_len);
8019                                 nested_nspace [nspace_len] = '\0';
8020
8021                         } else {
8022                                 nested_name = (char *)mod->data;
8023                                 nested_nspace = NULL;
8024                         }
8025
8026                         if (nested_nspace) {
8027                                 if (ignorecase) {
8028                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8029                                                 match = FALSE;
8030                                 } else {
8031                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8032                                                 match = FALSE;
8033                                 }
8034                         }
8035                         if (match) {
8036                                 if (ignorecase) {
8037                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8038                                                 match = FALSE;
8039                                 } else {
8040                                         if (strcmp (klass->name, nested_name) != 0)
8041                                                 match = FALSE;
8042                                 }
8043                         }
8044                         if (lastp) {
8045                                 g_free (nested_name);
8046                                 g_free (nested_nspace);
8047                         }
8048                         if (match)
8049                                 break;
8050                 }
8051
8052                 if (!klass)
8053                         break;
8054         }
8055         if (!klass)
8056                 return NULL;
8057
8058         if (info->type_arguments) {
8059                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8060                 MonoReflectionType *the_type;
8061                 MonoType *instance;
8062                 int i;
8063
8064                 for (i = 0; i < info->type_arguments->len; i++) {
8065                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8066
8067                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8068                         if (!type_args [i]) {
8069                                 g_free (type_args);
8070                                 return NULL;
8071                         }
8072                 }
8073
8074                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8075                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8076
8077                 instance = mono_reflection_bind_generic_parameters (
8078                         the_type, info->type_arguments->len, type_args);
8079
8080                 g_free (type_args);
8081                 if (!instance)
8082                         return NULL;
8083
8084                 klass = mono_class_from_mono_type (instance);
8085         }
8086
8087         for (mod = info->modifiers; mod; mod = mod->next) {
8088                 modval = GPOINTER_TO_UINT (mod->data);
8089                 if (!modval) { /* byref: must be last modifier */
8090                         return &klass->this_arg;
8091                 } else if (modval == -1) {
8092                         klass = mono_ptr_class_get (&klass->byval_arg);
8093                 } else if (modval == -2) {
8094                         bounded = TRUE;
8095                 } else { /* array rank */
8096                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8097                 }
8098         }
8099
8100         return &klass->byval_arg;
8101 }
8102
8103 /*
8104  * mono_reflection_get_type:
8105  * @image: a metadata context
8106  * @info: type description structure
8107  * @ignorecase: flag for case-insensitive string compares
8108  * @type_resolve: whenever type resolve was already tried
8109  *
8110  * Build a MonoType from the type description in @info.
8111  * 
8112  */
8113
8114 MonoType*
8115 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8116         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8117 }
8118
8119 static MonoType*
8120 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8121 {
8122         MonoReflectionAssemblyBuilder *abuilder;
8123         MonoType *type;
8124         int i;
8125
8126         g_assert (assembly_is_dynamic (assembly));
8127         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8128
8129         /* Enumerate all modules */
8130
8131         type = NULL;
8132         if (abuilder->modules) {
8133                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8134                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8135                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8136                         if (type)
8137                                 break;
8138                 }
8139         }
8140
8141         if (!type && abuilder->loaded_modules) {
8142                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8143                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8144                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8145                         if (type)
8146                                 break;
8147                 }
8148         }
8149
8150         return type;
8151 }
8152         
8153 MonoType*
8154 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8155 {
8156         MonoType *type;
8157         MonoReflectionAssembly *assembly;
8158         GString *fullName;
8159         GList *mod;
8160
8161         if (image && image_is_dynamic (image))
8162                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8163         else
8164                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8165         if (type)
8166                 return type;
8167         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8168                 return NULL;
8169
8170         if (type_resolve) {
8171                 if (*type_resolve) 
8172                         return NULL;
8173                 else
8174                         *type_resolve = TRUE;
8175         }
8176         
8177         /* Reconstruct the type name */
8178         fullName = g_string_new ("");
8179         if (info->name_space && (info->name_space [0] != '\0'))
8180                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8181         else
8182                 g_string_printf (fullName, "%s", info->name);
8183         for (mod = info->nested; mod; mod = mod->next)
8184                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8185
8186         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8187         if (assembly) {
8188                 if (assembly_is_dynamic (assembly->assembly))
8189                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8190                 else
8191                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8192                                                                                                           info, ignorecase);
8193         }
8194         g_string_free (fullName, TRUE);
8195         return type;
8196 }
8197
8198 void
8199 mono_reflection_free_type_info (MonoTypeNameParse *info)
8200 {
8201         g_list_free (info->modifiers);
8202         g_list_free (info->nested);
8203
8204         if (info->type_arguments) {
8205                 int i;
8206
8207                 for (i = 0; i < info->type_arguments->len; i++) {
8208                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8209
8210                         mono_reflection_free_type_info (subinfo);
8211                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8212                         g_free (subinfo);
8213                 }
8214
8215                 g_ptr_array_free (info->type_arguments, TRUE);
8216         }
8217 }
8218
8219 /*
8220  * mono_reflection_type_from_name:
8221  * @name: type name.
8222  * @image: a metadata context (can be NULL).
8223  *
8224  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8225  * it defaults to get the type from @image or, if @image is NULL or loading
8226  * from it fails, uses corlib.
8227  * 
8228  */
8229 MonoType*
8230 mono_reflection_type_from_name (char *name, MonoImage *image)
8231 {
8232         MonoType *type = NULL;
8233         MonoTypeNameParse info;
8234         char *tmp;
8235
8236         /* Make a copy since parse_type modifies its argument */
8237         tmp = g_strdup (name);
8238         
8239         /*g_print ("requested type %s\n", str);*/
8240         if (mono_reflection_parse_type (tmp, &info)) {
8241                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8242         }
8243
8244         g_free (tmp);
8245         mono_reflection_free_type_info (&info);
8246         return type;
8247 }
8248
8249 /*
8250  * mono_reflection_get_token:
8251  *
8252  *   Return the metadata token of OBJ which should be an object
8253  * representing a metadata element.
8254  */
8255 guint32
8256 mono_reflection_get_token (MonoObject *obj)
8257 {
8258         MonoClass *klass;
8259         guint32 token = 0;
8260
8261         klass = obj->vtable->klass;
8262
8263         if (strcmp (klass->name, "MethodBuilder") == 0) {
8264                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8265
8266                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8267         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8268                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8269
8270                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8271         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8272                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8273
8274                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8275         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8276                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8277                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8278         } else if (strcmp (klass->name, "MonoType") == 0) {
8279                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8280                 MonoClass *mc = mono_class_from_mono_type (type);
8281                 if (!mono_class_init (mc))
8282                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8283
8284                 token = mc->type_token;
8285         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8286                    strcmp (klass->name, "MonoMethod") == 0 ||
8287                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8288                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8289                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8290                 if (m->method->is_inflated) {
8291                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8292                         return inflated->declaring->token;
8293                 } else {
8294                         token = m->method->token;
8295                 }
8296         } else if (strcmp (klass->name, "MonoField") == 0) {
8297                 MonoReflectionField *f = (MonoReflectionField*)obj;
8298
8299                 if (is_field_on_inst (f->field)) {
8300                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8301
8302                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8303                                 int field_index = f->field - dgclass->fields;
8304                                 MonoObject *obj;
8305
8306                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8307                                 obj = dgclass->field_objects [field_index];
8308                                 return mono_reflection_get_token (obj);
8309                         }
8310                 }
8311                 token = mono_class_get_field_token (f->field);
8312         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8313                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8314
8315                 token = mono_class_get_property_token (p->property);
8316         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8317                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8318
8319                 token = mono_class_get_event_token (p->event);
8320         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8321                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8322                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8323                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8324
8325                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8326         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8327                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8328
8329                 token = m->token;
8330         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8331                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8332         } else {
8333                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8334                 MonoException *ex = mono_get_exception_not_implemented (msg);
8335                 g_free (msg);
8336                 mono_raise_exception (ex);
8337         }
8338
8339         return token;
8340 }
8341
8342 static MonoClass*
8343 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8344 {
8345         char *n;
8346         MonoType *t;
8347         int slen = mono_metadata_decode_value (p, &p);
8348
8349         mono_error_init (error);
8350
8351         n = (char *)g_memdup (p, slen + 1);
8352         n [slen] = 0;
8353         t = mono_reflection_type_from_name (n, image);
8354         if (!t) {
8355                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8356                 /* We don't free n, it's consumed by mono_error */
8357                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8358                 return NULL;
8359         }
8360         g_free (n);
8361         p += slen;
8362         *end = p;
8363         return mono_class_from_mono_type (t);
8364 }
8365
8366 static void*
8367 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8368 {
8369         int slen, type = t->type;
8370         MonoClass *tklass = t->data.klass;
8371
8372         mono_error_init (error);
8373
8374 handle_enum:
8375         switch (type) {
8376         case MONO_TYPE_U1:
8377         case MONO_TYPE_I1:
8378         case MONO_TYPE_BOOLEAN: {
8379                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8380                 *bval = *p;
8381                 *end = p + 1;
8382                 return bval;
8383         }
8384         case MONO_TYPE_CHAR:
8385         case MONO_TYPE_U2:
8386         case MONO_TYPE_I2: {
8387                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8388                 *val = read16 (p);
8389                 *end = p + 2;
8390                 return val;
8391         }
8392 #if SIZEOF_VOID_P == 4
8393         case MONO_TYPE_U:
8394         case MONO_TYPE_I:
8395 #endif
8396         case MONO_TYPE_R4:
8397         case MONO_TYPE_U4:
8398         case MONO_TYPE_I4: {
8399                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8400                 *val = read32 (p);
8401                 *end = p + 4;
8402                 return val;
8403         }
8404 #if SIZEOF_VOID_P == 8
8405         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8406         case MONO_TYPE_I:
8407 #endif
8408         case MONO_TYPE_U8:
8409         case MONO_TYPE_I8: {
8410                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8411                 *val = read64 (p);
8412                 *end = p + 8;
8413                 return val;
8414         }
8415         case MONO_TYPE_R8: {
8416                 double *val = (double *)g_malloc (sizeof (double));
8417                 readr8 (p, val);
8418                 *end = p + 8;
8419                 return val;
8420         }
8421         case MONO_TYPE_VALUETYPE:
8422                 if (t->data.klass->enumtype) {
8423                         type = mono_class_enum_basetype (t->data.klass)->type;
8424                         goto handle_enum;
8425                 } else {
8426                         MonoClass *k =  t->data.klass;
8427                         
8428                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8429                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8430                                 *val = read64 (p);
8431                                 *end = p + 8;
8432                                 return val;
8433                         }
8434                 }
8435                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8436                 break;
8437                 
8438         case MONO_TYPE_STRING:
8439                 if (*p == (char)0xFF) {
8440                         *end = p + 1;
8441                         return NULL;
8442                 }
8443                 slen = mono_metadata_decode_value (p, &p);
8444                 *end = p + slen;
8445                 return mono_string_new_len (mono_domain_get (), p, slen);
8446         case MONO_TYPE_CLASS: {
8447                 MonoReflectionType *rt;
8448                 char *n;
8449                 MonoType *t;
8450                 if (*p == (char)0xFF) {
8451                         *end = p + 1;
8452                         return NULL;
8453                 }
8454 handle_type:
8455                 slen = mono_metadata_decode_value (p, &p);
8456                 n = (char *)g_memdup (p, slen + 1);
8457                 n [slen] = 0;
8458                 t = mono_reflection_type_from_name (n, image);
8459                 if (!t) {
8460                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8461                         /* We don't free n, it's consumed by mono_error */
8462                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8463                         return NULL;
8464                 }
8465                 g_free (n);
8466                 *end = p + slen;
8467
8468                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8469                 if (!mono_error_ok (error))
8470                         return NULL;
8471
8472                 return rt;
8473         }
8474         case MONO_TYPE_OBJECT: {
8475                 char subt = *p++;
8476                 MonoObject *obj;
8477                 MonoClass *subc = NULL;
8478                 void *val;
8479
8480                 if (subt == 0x50) {
8481                         goto handle_type;
8482                 } else if (subt == 0x0E) {
8483                         type = MONO_TYPE_STRING;
8484                         goto handle_enum;
8485                 } else if (subt == 0x1D) {
8486                         MonoType simple_type = {{0}};
8487                         int etype = *p;
8488                         p ++;
8489
8490                         type = MONO_TYPE_SZARRAY;
8491                         if (etype == 0x50) {
8492                                 tklass = mono_defaults.systemtype_class;
8493                         } else if (etype == 0x55) {
8494                                 tklass = load_cattr_enum_type (image, p, &p, error);
8495                                 if (!mono_error_ok (error))
8496                                         return NULL;
8497                         } else {
8498                                 if (etype == 0x51)
8499                                         /* See Partition II, Appendix B3 */
8500                                         etype = MONO_TYPE_OBJECT;
8501                                 simple_type.type = (MonoTypeEnum)etype;
8502                                 tklass = mono_class_from_mono_type (&simple_type);
8503                         }
8504                         goto handle_enum;
8505                 } else if (subt == 0x55) {
8506                         char *n;
8507                         MonoType *t;
8508                         slen = mono_metadata_decode_value (p, &p);
8509                         n = (char *)g_memdup (p, slen + 1);
8510                         n [slen] = 0;
8511                         t = mono_reflection_type_from_name (n, image);
8512                         if (!t) {
8513                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8514                                 /* We don't free n, it's consumed by mono_error */
8515                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8516                                 return NULL;
8517                         }
8518                         g_free (n);
8519                         p += slen;
8520                         subc = mono_class_from_mono_type (t);
8521                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8522                         MonoType simple_type = {{0}};
8523                         simple_type.type = (MonoTypeEnum)subt;
8524                         subc = mono_class_from_mono_type (&simple_type);
8525                 } else {
8526                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8527                 }
8528                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8529                 obj = NULL;
8530                 if (mono_error_ok (error)) {
8531                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8532                         g_assert (!subc->has_references);
8533                         if (mono_error_ok (error))
8534                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8535                 }
8536
8537                 g_free (val);
8538                 return obj;
8539         }
8540         case MONO_TYPE_SZARRAY: {
8541                 MonoArray *arr;
8542                 guint32 i, alen, basetype;
8543                 alen = read32 (p);
8544                 p += 4;
8545                 if (alen == 0xffffffff) {
8546                         *end = p;
8547                         return NULL;
8548                 }
8549                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8550                 basetype = tklass->byval_arg.type;
8551                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8552                         basetype = mono_class_enum_basetype (tklass)->type;
8553                 switch (basetype)
8554                 {
8555                         case MONO_TYPE_U1:
8556                         case MONO_TYPE_I1:
8557                         case MONO_TYPE_BOOLEAN:
8558                                 for (i = 0; i < alen; i++) {
8559                                         MonoBoolean val = *p++;
8560                                         mono_array_set (arr, MonoBoolean, i, val);
8561                                 }
8562                                 break;
8563                         case MONO_TYPE_CHAR:
8564                         case MONO_TYPE_U2:
8565                         case MONO_TYPE_I2:
8566                                 for (i = 0; i < alen; i++) {
8567                                         guint16 val = read16 (p);
8568                                         mono_array_set (arr, guint16, i, val);
8569                                         p += 2;
8570                                 }
8571                                 break;
8572                         case MONO_TYPE_R4:
8573                         case MONO_TYPE_U4:
8574                         case MONO_TYPE_I4:
8575                                 for (i = 0; i < alen; i++) {
8576                                         guint32 val = read32 (p);
8577                                         mono_array_set (arr, guint32, i, val);
8578                                         p += 4;
8579                                 }
8580                                 break;
8581                         case MONO_TYPE_R8:
8582                                 for (i = 0; i < alen; i++) {
8583                                         double val;
8584                                         readr8 (p, &val);
8585                                         mono_array_set (arr, double, i, val);
8586                                         p += 8;
8587                                 }
8588                                 break;
8589                         case MONO_TYPE_U8:
8590                         case MONO_TYPE_I8:
8591                                 for (i = 0; i < alen; i++) {
8592                                         guint64 val = read64 (p);
8593                                         mono_array_set (arr, guint64, i, val);
8594                                         p += 8;
8595                                 }
8596                                 break;
8597                         case MONO_TYPE_CLASS:
8598                         case MONO_TYPE_OBJECT:
8599                         case MONO_TYPE_STRING:
8600                         case MONO_TYPE_SZARRAY:
8601                                 for (i = 0; i < alen; i++) {
8602                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8603                                         if (!mono_error_ok (error))
8604                                                 return NULL;
8605                                         mono_array_setref (arr, i, item);
8606                                 }
8607                                 break;
8608                         default:
8609                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8610                 }
8611                 *end=p;
8612                 return arr;
8613         }
8614         default:
8615                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8616         }
8617         return NULL;
8618 }
8619
8620 static MonoObject*
8621 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8622 {
8623         static MonoClass *klass;
8624         static MonoMethod *ctor;
8625         MonoError error;
8626         MonoObject *retval;
8627         void *params [2], *unboxed;
8628
8629         if (!klass)
8630                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8631         if (!ctor)
8632                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8633         
8634         params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8635         mono_error_raise_exception (&error); /* FIXME don't raise here */
8636
8637         params [1] = val;
8638         retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8639         mono_error_raise_exception (&error); /* FIXME don't raise here */
8640         unboxed = mono_object_unbox (retval);
8641         mono_runtime_invoke (ctor, unboxed, params, NULL);
8642
8643         return retval;
8644 }
8645
8646 static MonoObject*
8647 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8648 {
8649         static MonoClass *klass;
8650         static MonoMethod *ctor;
8651         MonoError error;
8652         MonoObject *retval;
8653         void *unboxed, *params [2];
8654
8655         if (!klass)
8656                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8657         if (!ctor)
8658                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8659
8660         params [0] = minfo;
8661         params [1] = typedarg;
8662         retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8663         mono_error_raise_exception (&error); /* FIXME don't raise here */
8664         unboxed = mono_object_unbox (retval);
8665         mono_runtime_invoke (ctor, unboxed, params, NULL);
8666
8667         return retval;
8668 }
8669
8670 static gboolean
8671 type_is_reference (MonoType *type)
8672 {
8673         switch (type->type) {
8674         case MONO_TYPE_BOOLEAN:
8675         case MONO_TYPE_CHAR:
8676         case MONO_TYPE_U:
8677         case MONO_TYPE_I:
8678         case MONO_TYPE_U1:
8679         case MONO_TYPE_I1:
8680         case MONO_TYPE_U2:
8681         case MONO_TYPE_I2:
8682         case MONO_TYPE_U4:
8683         case MONO_TYPE_I4:
8684         case MONO_TYPE_U8:
8685         case MONO_TYPE_I8:
8686         case MONO_TYPE_R8:
8687         case MONO_TYPE_R4:
8688         case MONO_TYPE_VALUETYPE:
8689                 return FALSE;
8690         default:
8691                 return TRUE;
8692         }
8693 }
8694
8695 static void
8696 free_param_data (MonoMethodSignature *sig, void **params) {
8697         int i;
8698         for (i = 0; i < sig->param_count; ++i) {
8699                 if (!type_is_reference (sig->params [i]))
8700                         g_free (params [i]);
8701         }
8702 }
8703
8704 /*
8705  * Find the field index in the metadata FieldDef table.
8706  */
8707 static guint32
8708 find_field_index (MonoClass *klass, MonoClassField *field) {
8709         int i;
8710
8711         for (i = 0; i < klass->field.count; ++i) {
8712                 if (field == &klass->fields [i])
8713                         return klass->field.first + 1 + i;
8714         }
8715         return 0;
8716 }
8717
8718 /*
8719  * Find the property index in the metadata Property table.
8720  */
8721 static guint32
8722 find_property_index (MonoClass *klass, MonoProperty *property) {
8723         int i;
8724
8725         for (i = 0; i < klass->ext->property.count; ++i) {
8726                 if (property == &klass->ext->properties [i])
8727                         return klass->ext->property.first + 1 + i;
8728         }
8729         return 0;
8730 }
8731
8732 /*
8733  * Find the event index in the metadata Event table.
8734  */
8735 static guint32
8736 find_event_index (MonoClass *klass, MonoEvent *event) {
8737         int i;
8738
8739         for (i = 0; i < klass->ext->event.count; ++i) {
8740                 if (event == &klass->ext->events [i])
8741                         return klass->ext->event.first + 1 + i;
8742         }
8743         return 0;
8744 }
8745
8746 static MonoObject*
8747 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8748 {
8749         const char *p = (const char*)data;
8750         const char *named;
8751         guint32 i, j, num_named;
8752         MonoObject *attr;
8753         void *params_buf [32];
8754         void **params = NULL;
8755         MonoMethodSignature *sig;
8756         MonoObject *exc = NULL;
8757
8758         mono_error_init (error);
8759
8760         mono_class_init (method->klass);
8761
8762         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8763                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8764                 return NULL;
8765         }
8766
8767         if (len == 0) {
8768                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8769                 if (!mono_error_ok (error)) return NULL;
8770                 mono_runtime_invoke (method, attr, NULL, NULL);
8771                 return attr;
8772         }
8773
8774         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8775                 return NULL;
8776
8777         /*g_print ("got attr %s\n", method->klass->name);*/
8778
8779         sig = mono_method_signature (method);
8780         if (sig->param_count < 32) {
8781                 params = params_buf;
8782                 memset (params, 0, sizeof (void*) * sig->param_count);
8783         } else {
8784                 /* Allocate using GC so it gets GC tracking */
8785                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8786         }
8787
8788         /* skip prolog */
8789         p += 2;
8790         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8791                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8792                 if (!mono_error_ok (error))
8793                         goto fail;
8794         }
8795
8796         named = p;
8797         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8798         if (!mono_error_ok (error)) goto fail;
8799
8800         mono_runtime_invoke (method, attr, params, &exc);
8801         if (exc)
8802                 goto fail;
8803         num_named = read16 (named);
8804         named += 2;
8805         for (j = 0; j < num_named; j++) {
8806                 gint name_len;
8807                 char *name, named_type, data_type;
8808                 named_type = *named++;
8809                 data_type = *named++; /* type of data */
8810                 if (data_type == MONO_TYPE_SZARRAY)
8811                         data_type = *named++;
8812                 if (data_type == MONO_TYPE_ENUM) {
8813                         gint type_len;
8814                         char *type_name;
8815                         type_len = mono_metadata_decode_blob_size (named, &named);
8816                         type_name = (char *)g_malloc (type_len + 1);
8817                         memcpy (type_name, named, type_len);
8818                         type_name [type_len] = 0;
8819                         named += type_len;
8820                         /* FIXME: lookup the type and check type consistency */
8821                         g_free (type_name);
8822                 }
8823                 name_len = mono_metadata_decode_blob_size (named, &named);
8824                 name = (char *)g_malloc (name_len + 1);
8825                 memcpy (name, named, name_len);
8826                 name [name_len] = 0;
8827                 named += name_len;
8828                 if (named_type == 0x53) {
8829                         MonoClassField *field;
8830                         void *val;
8831
8832                         /* how this fail is a blackbox */
8833                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8834                         if (!field) {
8835                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8836                                 g_free (name);
8837                                 goto fail;
8838                         }
8839
8840                         val = load_cattr_value (image, field->type, named, &named, error);
8841                         if (!mono_error_ok (error)) {
8842                                 g_free (name);
8843                                 if (!type_is_reference (field->type))
8844                                         g_free (val);
8845                                 goto fail;
8846                         }
8847
8848                         mono_field_set_value (attr, field, val);
8849                         if (!type_is_reference (field->type))
8850                                 g_free (val);
8851                 } else if (named_type == 0x54) {
8852                         MonoProperty *prop;
8853                         void *pparams [1];
8854                         MonoType *prop_type;
8855
8856                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8857
8858                         if (!prop) {
8859                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8860                                 g_free (name);
8861                                 goto fail;
8862                         }
8863
8864                         if (!prop->set) {
8865                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8866                                 g_free (name);
8867                                 goto fail;
8868                         }
8869
8870                         /* can we have more that 1 arg in a custom attr named property? */
8871                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8872                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8873
8874                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8875                         if (!mono_error_ok (error)) {
8876                                 g_free (name);
8877                                 if (!type_is_reference (prop_type))
8878                                         g_free (pparams [0]);
8879                                 goto fail;
8880                         }
8881
8882
8883                         mono_property_set_value (prop, attr, pparams, NULL);
8884                         if (!type_is_reference (prop_type))
8885                                 g_free (pparams [0]);
8886                 }
8887                 g_free (name);
8888         }
8889
8890         free_param_data (method->signature, params);
8891         if (params != params_buf)
8892                 mono_gc_free_fixed (params);
8893
8894         return attr;
8895
8896 fail:
8897         free_param_data (method->signature, params);
8898         if (params != params_buf)
8899                 mono_gc_free_fixed (params);
8900         if (exc)
8901                 mono_raise_exception ((MonoException*)exc);
8902         return NULL;
8903 }
8904         
8905 /*
8906  * mono_reflection_create_custom_attr_data_args:
8907  *
8908  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8909  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8910  * NAMED_ARG_INFO will contain information about the named arguments.
8911  */
8912 void
8913 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)
8914 {
8915         MonoArray *typedargs, *namedargs;
8916         MonoClass *attrklass;
8917         MonoDomain *domain;
8918         const char *p = (const char*)data;
8919         const char *named;
8920         guint32 i, j, num_named;
8921         CattrNamedArg *arginfo = NULL;
8922
8923         *typed_args = NULL;
8924         *named_args = NULL;
8925         *named_arg_info = NULL;
8926
8927         mono_error_init (error);
8928
8929         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8930                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8931                 return;
8932         }
8933
8934         mono_class_init (method->klass);
8935         
8936         domain = mono_domain_get ();
8937
8938         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8939                 return;
8940
8941         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8942         
8943         /* skip prolog */
8944         p += 2;
8945         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8946                 MonoObject *obj;
8947                 void *val;
8948
8949                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8950                 if (!mono_error_ok (error)) {
8951                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8952                                 g_free (val);
8953                         return;
8954                 }
8955
8956                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8957                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8958                 mono_array_setref (typedargs, i, obj);
8959
8960                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8961                         g_free (val);
8962         }
8963
8964         named = p;
8965         num_named = read16 (named);
8966         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8967         named += 2;
8968         attrklass = method->klass;
8969
8970         arginfo = g_new0 (CattrNamedArg, num_named);
8971         *named_arg_info = arginfo;
8972
8973         for (j = 0; j < num_named; j++) {
8974                 gint name_len;
8975                 char *name, named_type, data_type;
8976                 named_type = *named++;
8977                 data_type = *named++; /* type of data */
8978                 if (data_type == MONO_TYPE_SZARRAY)
8979                         data_type = *named++;
8980                 if (data_type == MONO_TYPE_ENUM) {
8981                         gint type_len;
8982                         char *type_name;
8983                         type_len = mono_metadata_decode_blob_size (named, &named);
8984                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8985                                 goto fail;
8986
8987                         type_name = (char *)g_malloc (type_len + 1);
8988                         memcpy (type_name, named, type_len);
8989                         type_name [type_len] = 0;
8990                         named += type_len;
8991                         /* FIXME: lookup the type and check type consistency */
8992                         g_free (type_name);
8993                 }
8994                 name_len = mono_metadata_decode_blob_size (named, &named);
8995                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8996                         goto fail;
8997                 name = (char *)g_malloc (name_len + 1);
8998                 memcpy (name, named, name_len);
8999                 name [name_len] = 0;
9000                 named += name_len;
9001                 if (named_type == 0x53) {
9002                         MonoObject *obj;
9003                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9004                         void *val;
9005
9006                         if (!field) {
9007                                 g_free (name);
9008                                 goto fail;
9009                         }
9010
9011                         arginfo [j].type = field->type;
9012                         arginfo [j].field = field;
9013
9014                         val = load_cattr_value (image, field->type, named, &named, error);
9015                         if (!mono_error_ok (error)) {
9016                                 if (!type_is_reference (field->type))
9017                                         g_free (val);
9018                                 g_free (name);
9019                                 return;
9020                         }
9021
9022                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9023                         mono_array_setref (namedargs, j, obj);
9024                         if (!type_is_reference (field->type))
9025                                 g_free (val);
9026                 } else if (named_type == 0x54) {
9027                         MonoObject *obj;
9028                         MonoType *prop_type;
9029                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9030                         void *val;
9031
9032                         if (!prop || !prop->set) {
9033                                 g_free (name);
9034                                 goto fail;
9035                         }
9036
9037                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9038                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9039
9040                         arginfo [j].type = prop_type;
9041                         arginfo [j].prop = prop;
9042
9043                         val = load_cattr_value (image, prop_type, named, &named, error);
9044                         if (!mono_error_ok (error)) {
9045                                 if (!type_is_reference (prop_type))
9046                                         g_free (val);
9047                                 g_free (name);
9048                                 return;
9049                         }
9050
9051                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9052                         mono_array_setref (namedargs, j, obj);
9053                         if (!type_is_reference (prop_type))
9054                                 g_free (val);
9055                 }
9056                 g_free (name);
9057         }
9058
9059         *typed_args = typedargs;
9060         *named_args = namedargs;
9061         return;
9062 fail:
9063         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9064         g_free (arginfo);
9065         *named_arg_info = NULL;
9066 }
9067
9068 void
9069 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9070 {
9071         MonoDomain *domain;
9072         MonoArray *typedargs, *namedargs;
9073         MonoImage *image;
9074         MonoMethod *method;
9075         CattrNamedArg *arginfo = NULL;
9076         MonoError error;
9077         int i;
9078
9079         mono_error_init (&error);
9080
9081         *ctor_args = NULL;
9082         *named_args = NULL;
9083
9084         if (len == 0)
9085                 return;
9086
9087         image = assembly->assembly->image;
9088         method = ref_method->method;
9089         domain = mono_object_domain (ref_method);
9090
9091         if (!mono_class_init (method->klass))
9092                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9093
9094         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9095         if (!mono_error_ok (&error))
9096                 goto leave;
9097
9098         if (mono_loader_get_last_error ()) {
9099                 mono_error_set_from_loader_error (&error);
9100                 goto leave;
9101         }
9102
9103         if (!typedargs || !namedargs)
9104                 goto leave;
9105
9106         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9107                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9108                 MonoObject *typedarg;
9109
9110                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9111                 mono_array_setref (typedargs, i, typedarg);
9112         }
9113
9114         for (i = 0; i < mono_array_length (namedargs); ++i) {
9115                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9116                 MonoObject *typedarg, *namedarg, *minfo;
9117
9118                 if (arginfo [i].prop)
9119                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9120                 else {
9121                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9122                         if (!mono_error_ok (&error))
9123                                 goto leave;
9124                 }
9125
9126                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9127                 namedarg = create_cattr_named_arg (minfo, typedarg);
9128
9129                 mono_array_setref (namedargs, i, namedarg);
9130         }
9131
9132         *ctor_args = typedargs;
9133         *named_args = namedargs;
9134 leave:
9135         g_free (arginfo);
9136         mono_error_raise_exception (&error);
9137
9138 }
9139
9140 static MonoObject*
9141 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9142 {
9143         static MonoMethod *ctor;
9144
9145         MonoError error;
9146         MonoDomain *domain;
9147         MonoObject *attr;
9148         void *params [4];
9149
9150         g_assert (image->assembly);
9151
9152         if (!ctor)
9153                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9154
9155         domain = mono_domain_get ();
9156         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9157         mono_error_raise_exception (&error); /* FIXME don't raise here */
9158         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9159         mono_error_raise_exception (&error); /* FIXME don't raise here */
9160         params [1] = mono_assembly_get_object (domain, image->assembly);
9161         params [2] = (gpointer)&cattr->data;
9162         params [3] = &cattr->data_size;
9163         mono_runtime_invoke (ctor, attr, params, NULL);
9164         return attr;
9165 }
9166
9167 static MonoArray*
9168 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9169 {
9170         MonoArray *result;
9171         MonoObject *attr;
9172         int i, n;
9173
9174         mono_error_init (error);
9175
9176         n = 0;
9177         for (i = 0; i < cinfo->num_attrs; ++i) {
9178                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9179                         n ++;
9180         }
9181
9182         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9183         n = 0;
9184         for (i = 0; i < cinfo->num_attrs; ++i) {
9185                 if (!cinfo->attrs [i].ctor)
9186                         /* The cattr type is not finished yet */
9187                         /* We should include the type name but cinfo doesn't contain it */
9188                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9189                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9190                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9191                         if (!mono_error_ok (error))
9192                                 return result;
9193                         mono_array_setref (result, n, attr);
9194                         n ++;
9195                 }
9196         }
9197         return result;
9198 }
9199
9200 MonoArray*
9201 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9202 {
9203         MonoError error;
9204         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9205         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9206
9207         return result;
9208 }
9209
9210 static MonoArray*
9211 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9212 {
9213         MonoArray *result;
9214         MonoObject *attr;
9215         int i;
9216         
9217         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9218         for (i = 0; i < cinfo->num_attrs; ++i) {
9219                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9220                 mono_array_setref (result, i, attr);
9221         }
9222         return result;
9223 }
9224
9225 /**
9226  * mono_custom_attrs_from_index:
9227  *
9228  * Returns: NULL if no attributes are found or if a loading error occurs.
9229  */
9230 MonoCustomAttrInfo*
9231 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9232 {
9233         guint32 mtoken, i, len;
9234         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9235         MonoTableInfo *ca;
9236         MonoCustomAttrInfo *ainfo;
9237         GList *tmp, *list = NULL;
9238         const char *data;
9239         MonoCustomAttrEntry* attr;
9240
9241         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9242
9243         i = mono_metadata_custom_attrs_from_index (image, idx);
9244         if (!i)
9245                 return NULL;
9246         i --;
9247         while (i < ca->rows) {
9248                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9249                         break;
9250                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9251                 ++i;
9252         }
9253         len = g_list_length (list);
9254         if (!len)
9255                 return NULL;
9256         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9257         ainfo->num_attrs = len;
9258         ainfo->image = image;
9259         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9260                 MonoError error;
9261                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9262                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9263                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9264                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9265                         mtoken |= MONO_TOKEN_METHOD_DEF;
9266                         break;
9267                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9268                         mtoken |= MONO_TOKEN_MEMBER_REF;
9269                         break;
9270                 default:
9271                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9272                         break;
9273                 }
9274                 attr = &ainfo->attrs [i - 1];
9275                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9276                 if (!attr->ctor) {
9277                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9278                         mono_loader_set_error_from_mono_error (&error);
9279                         g_list_free (list);
9280                         g_free (ainfo);
9281                         return NULL;
9282                 }
9283
9284                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9285                         /*FIXME raising an exception here doesn't make any sense*/
9286                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9287                         g_list_free (list);
9288                         g_free (ainfo);
9289                         return NULL;
9290                 }
9291                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9292                 attr->data_size = mono_metadata_decode_value (data, &data);
9293                 attr->data = (guchar*)data;
9294         }
9295         g_list_free (list);
9296
9297         return ainfo;
9298 }
9299
9300 MonoCustomAttrInfo*
9301 mono_custom_attrs_from_method (MonoMethod *method)
9302 {
9303         guint32 idx;
9304
9305         /*
9306          * An instantiated method has the same cattrs as the generic method definition.
9307          *
9308          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9309          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9310          */
9311         if (method->is_inflated)
9312                 method = ((MonoMethodInflated *) method)->declaring;
9313         
9314         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9315                 return lookup_custom_attr (method->klass->image, method);
9316
9317         if (!method->token)
9318                 /* Synthetic methods */
9319                 return NULL;
9320
9321         idx = mono_method_get_index (method);
9322         idx <<= MONO_CUSTOM_ATTR_BITS;
9323         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9324         return mono_custom_attrs_from_index (method->klass->image, idx);
9325 }
9326
9327 MonoCustomAttrInfo*
9328 mono_custom_attrs_from_class (MonoClass *klass)
9329 {
9330         guint32 idx;
9331
9332         if (klass->generic_class)
9333                 klass = klass->generic_class->container_class;
9334
9335         if (image_is_dynamic (klass->image))
9336                 return lookup_custom_attr (klass->image, klass);
9337
9338         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9339                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9340                 idx <<= MONO_CUSTOM_ATTR_BITS;
9341                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9342         } else {
9343                 idx = mono_metadata_token_index (klass->type_token);
9344                 idx <<= MONO_CUSTOM_ATTR_BITS;
9345                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9346         }
9347         return mono_custom_attrs_from_index (klass->image, idx);
9348 }
9349
9350 MonoCustomAttrInfo*
9351 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9352 {
9353         guint32 idx;
9354         
9355         if (image_is_dynamic (assembly->image))
9356                 return lookup_custom_attr (assembly->image, assembly);
9357         idx = 1; /* there is only one assembly */
9358         idx <<= MONO_CUSTOM_ATTR_BITS;
9359         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9360         return mono_custom_attrs_from_index (assembly->image, idx);
9361 }
9362
9363 static MonoCustomAttrInfo*
9364 mono_custom_attrs_from_module (MonoImage *image)
9365 {
9366         guint32 idx;
9367         
9368         if (image_is_dynamic (image))
9369                 return lookup_custom_attr (image, image);
9370         idx = 1; /* there is only one module */
9371         idx <<= MONO_CUSTOM_ATTR_BITS;
9372         idx |= MONO_CUSTOM_ATTR_MODULE;
9373         return mono_custom_attrs_from_index (image, idx);
9374 }
9375
9376 MonoCustomAttrInfo*
9377 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9378 {
9379         guint32 idx;
9380         
9381         if (image_is_dynamic (klass->image)) {
9382                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9383                 return lookup_custom_attr (klass->image, property);
9384         }
9385         idx = find_property_index (klass, property);
9386         idx <<= MONO_CUSTOM_ATTR_BITS;
9387         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9388         return mono_custom_attrs_from_index (klass->image, idx);
9389 }
9390
9391 MonoCustomAttrInfo*
9392 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9393 {
9394         guint32 idx;
9395         
9396         if (image_is_dynamic (klass->image)) {
9397                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9398                 return lookup_custom_attr (klass->image, event);
9399         }
9400         idx = find_event_index (klass, event);
9401         idx <<= MONO_CUSTOM_ATTR_BITS;
9402         idx |= MONO_CUSTOM_ATTR_EVENT;
9403         return mono_custom_attrs_from_index (klass->image, idx);
9404 }
9405
9406 MonoCustomAttrInfo*
9407 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9408 {
9409         guint32 idx;
9410         if (image_is_dynamic (klass->image)) {
9411                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9412                 return lookup_custom_attr (klass->image, field);
9413         }
9414         idx = find_field_index (klass, field);
9415         idx <<= MONO_CUSTOM_ATTR_BITS;
9416         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9417         return mono_custom_attrs_from_index (klass->image, idx);
9418 }
9419
9420 /**
9421  * mono_custom_attrs_from_param:
9422  * @method: handle to the method that we want to retrieve custom parameter information from
9423  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9424  *
9425  * The result must be released with mono_custom_attrs_free().
9426  *
9427  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9428  */
9429 MonoCustomAttrInfo*
9430 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9431 {
9432         MonoTableInfo *ca;
9433         guint32 i, idx, method_index;
9434         guint32 param_list, param_last, param_pos, found;
9435         MonoImage *image;
9436         MonoReflectionMethodAux *aux;
9437
9438         /*
9439          * An instantiated method has the same cattrs as the generic method definition.
9440          *
9441          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9442          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9443          */
9444         if (method->is_inflated)
9445                 method = ((MonoMethodInflated *) method)->declaring;
9446
9447         if (image_is_dynamic (method->klass->image)) {
9448                 MonoCustomAttrInfo *res, *ainfo;
9449                 int size;
9450
9451                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9452                 if (!aux || !aux->param_cattr)
9453                         return NULL;
9454
9455                 /* Need to copy since it will be freed later */
9456                 ainfo = aux->param_cattr [param];
9457                 if (!ainfo)
9458                         return NULL;
9459                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9460                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9461                 memcpy (res, ainfo, size);
9462                 return res;
9463         }
9464
9465         image = method->klass->image;
9466         method_index = mono_method_get_index (method);
9467         if (!method_index)
9468                 return NULL;
9469         ca = &image->tables [MONO_TABLE_METHOD];
9470
9471         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9472         if (method_index == ca->rows) {
9473                 ca = &image->tables [MONO_TABLE_PARAM];
9474                 param_last = ca->rows + 1;
9475         } else {
9476                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9477                 ca = &image->tables [MONO_TABLE_PARAM];
9478         }
9479         found = FALSE;
9480         for (i = param_list; i < param_last; ++i) {
9481                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9482                 if (param_pos == param) {
9483                         found = TRUE;
9484                         break;
9485                 }
9486         }
9487         if (!found)
9488                 return NULL;
9489         idx = i;
9490         idx <<= MONO_CUSTOM_ATTR_BITS;
9491         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9492         return mono_custom_attrs_from_index (image, idx);
9493 }
9494
9495 gboolean
9496 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9497 {
9498         int i;
9499         MonoClass *klass;
9500         for (i = 0; i < ainfo->num_attrs; ++i) {
9501                 klass = ainfo->attrs [i].ctor->klass;
9502                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9503                         return TRUE;
9504         }
9505         return FALSE;
9506 }
9507
9508 MonoObject*
9509 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9510 {
9511         MonoError error;
9512         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9513         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9514         return res;
9515 }
9516
9517 MonoObject*
9518 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9519 {
9520         int i, attr_index;
9521         MonoClass *klass;
9522         MonoArray *attrs;
9523
9524         mono_error_init (error);
9525
9526         attr_index = -1;
9527         for (i = 0; i < ainfo->num_attrs; ++i) {
9528                 klass = ainfo->attrs [i].ctor->klass;
9529                 if (mono_class_has_parent (klass, attr_klass)) {
9530                         attr_index = i;
9531                         break;
9532                 }
9533         }
9534         if (attr_index == -1)
9535                 return NULL;
9536
9537         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9538         if (!mono_error_ok (error))
9539                 return NULL;
9540         return mono_array_get (attrs, MonoObject*, attr_index);
9541 }
9542
9543 /*
9544  * mono_reflection_get_custom_attrs_info:
9545  * @obj: a reflection object handle
9546  *
9547  * Return the custom attribute info for attributes defined for the
9548  * reflection handle @obj. The objects.
9549  *
9550  * FIXME this function leaks like a sieve for SRE objects.
9551  */
9552 MonoCustomAttrInfo*
9553 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9554 {
9555         MonoClass *klass;
9556         MonoCustomAttrInfo *cinfo = NULL;
9557         
9558         klass = obj->vtable->klass;
9559         if (klass == mono_defaults.monotype_class) {
9560                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9561                 klass = mono_class_from_mono_type (type);
9562                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9563                 cinfo = mono_custom_attrs_from_class (klass);
9564         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9565                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9566                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9567         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9568                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9569                 cinfo = mono_custom_attrs_from_module (module->image);
9570         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9571                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9572                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9573         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9574                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9575                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9576         } else if (strcmp ("MonoField", klass->name) == 0) {
9577                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9578                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9579         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9580                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9581                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9582         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9583                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9584                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9585         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9586                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9587                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9588                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9589                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9590                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9591                 } else if (is_sr_mono_property (member_class)) {
9592                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9593                         MonoMethod *method;
9594                         if (!(method = prop->property->get))
9595                                 method = prop->property->set;
9596                         g_assert (method);
9597
9598                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9599                 } 
9600 #ifndef DISABLE_REFLECTION_EMIT
9601                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9602                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9603                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9604                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9605                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9606                         MonoMethod *method = NULL;
9607                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9608                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9609                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9610                                 method = ((MonoReflectionMethod *)c->cb)->method;
9611                         else
9612                                 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));
9613
9614                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9615                 } 
9616 #endif
9617                 else {
9618                         char *type_name = mono_type_get_full_name (member_class);
9619                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9620                         MonoException *ex = mono_get_exception_not_supported  (msg);
9621                         g_free (type_name);
9622                         g_free (msg);
9623                         mono_raise_exception (ex);
9624                 }
9625         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9626                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9627                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9628         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9629                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9630                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9631         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9632                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9633                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9634         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9635                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9636                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9637         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9638                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9639                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9640         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9641                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9642                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9643         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9644                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9645                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9646         } else { /* handle other types here... */
9647                 g_error ("get custom attrs not yet supported for %s", klass->name);
9648         }
9649
9650         return cinfo;
9651 }
9652
9653 /*
9654  * mono_reflection_get_custom_attrs_by_type:
9655  * @obj: a reflection object handle
9656  *
9657  * Return an array with all the custom attributes defined of the
9658  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9659  * of that type are returned. The objects are fully build. Return NULL if a loading error
9660  * occurs.
9661  */
9662 MonoArray*
9663 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9664 {
9665         MonoArray *result;
9666         MonoCustomAttrInfo *cinfo;
9667
9668         mono_error_init (error);
9669
9670         cinfo = mono_reflection_get_custom_attrs_info (obj);
9671         if (cinfo) {
9672                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9673                 if (!cinfo->cached)
9674                         mono_custom_attrs_free (cinfo);
9675         } else {
9676                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9677                 if (mono_loader_get_last_error ())
9678                         return NULL;
9679                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9680         }
9681
9682         return result;
9683 }
9684
9685 /*
9686  * mono_reflection_get_custom_attrs:
9687  * @obj: a reflection object handle
9688  *
9689  * Return an array with all the custom attributes defined of the
9690  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9691  * occurs.
9692  */
9693 MonoArray*
9694 mono_reflection_get_custom_attrs (MonoObject *obj)
9695 {
9696         MonoError error;
9697
9698         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9699 }
9700
9701 /*
9702  * mono_reflection_get_custom_attrs_data:
9703  * @obj: a reflection obj handle
9704  *
9705  * Returns an array of System.Reflection.CustomAttributeData,
9706  * which include information about attributes reflected on
9707  * types loaded using the Reflection Only methods
9708  */
9709 MonoArray*
9710 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9711 {
9712         MonoArray *result;
9713         MonoCustomAttrInfo *cinfo;
9714
9715         cinfo = mono_reflection_get_custom_attrs_info (obj);
9716         if (cinfo) {
9717                 result = mono_custom_attrs_data_construct (cinfo);
9718                 if (!cinfo->cached)
9719                         mono_custom_attrs_free (cinfo);
9720         } else
9721                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9722
9723         return result;
9724 }
9725
9726 static MonoReflectionType*
9727 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9728 {
9729         static MonoMethod *method_get_underlying_system_type = NULL;
9730         MonoMethod *usertype_method;
9731
9732         if (!method_get_underlying_system_type)
9733                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9734         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9735         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9736 }
9737
9738
9739 static gboolean
9740 is_corlib_type (MonoClass *klass)
9741 {
9742         return klass->image == mono_defaults.corlib;
9743 }
9744
9745 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9746         static MonoClass *cached_class; \
9747         if (cached_class) \
9748                 return cached_class == _class; \
9749         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9750                 cached_class = _class; \
9751                 return TRUE; \
9752         } \
9753         return FALSE; \
9754 } while (0) \
9755
9756
9757 #ifndef DISABLE_REFLECTION_EMIT
9758 static gboolean
9759 is_sre_array (MonoClass *klass)
9760 {
9761         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9762 }
9763
9764 static gboolean
9765 is_sre_byref (MonoClass *klass)
9766 {
9767         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9768 }
9769
9770 static gboolean
9771 is_sre_pointer (MonoClass *klass)
9772 {
9773         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9774 }
9775
9776 static gboolean
9777 is_sre_generic_instance (MonoClass *klass)
9778 {
9779         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9780 }
9781
9782 static gboolean
9783 is_sre_type_builder (MonoClass *klass)
9784 {
9785         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9786 }
9787
9788 static gboolean
9789 is_sre_method_builder (MonoClass *klass)
9790 {
9791         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9792 }
9793
9794 static gboolean
9795 is_sre_ctor_builder (MonoClass *klass)
9796 {
9797         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9798 }
9799
9800 static gboolean
9801 is_sre_field_builder (MonoClass *klass)
9802 {
9803         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9804 }
9805
9806 static gboolean
9807 is_sre_method_on_tb_inst (MonoClass *klass)
9808 {
9809         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9810 }
9811
9812 static gboolean
9813 is_sre_ctor_on_tb_inst (MonoClass *klass)
9814 {
9815         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9816 }
9817
9818 MonoType*
9819 mono_reflection_type_get_handle (MonoReflectionType* ref)
9820 {
9821         MonoClass *klass;
9822         if (!ref)
9823                 return NULL;
9824         if (ref->type)
9825                 return ref->type;
9826
9827         if (is_usertype (ref)) {
9828                 ref = mono_reflection_type_get_underlying_system_type (ref);
9829                 if (ref == NULL || is_usertype (ref))
9830                         return NULL;
9831                 if (ref->type)
9832                         return ref->type;
9833         }
9834
9835         klass = mono_object_class (ref);
9836
9837         if (is_sre_array (klass)) {
9838                 MonoType *res;
9839                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9840                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9841                 g_assert (base);
9842                 if (sre_array->rank == 0) //single dimentional array
9843                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9844                 else
9845                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9846                 sre_array->type.type = res;
9847                 return res;
9848         } else if (is_sre_byref (klass)) {
9849                 MonoType *res;
9850                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9851                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9852                 g_assert (base);
9853                 res = &mono_class_from_mono_type (base)->this_arg;
9854                 sre_byref->type.type = res;
9855                 return res;
9856         } else if (is_sre_pointer (klass)) {
9857                 MonoType *res;
9858                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9859                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9860                 g_assert (base);
9861                 res = &mono_ptr_class_get (base)->byval_arg;
9862                 sre_pointer->type.type = res;
9863                 return res;
9864         } else if (is_sre_generic_instance (klass)) {
9865                 MonoType *res, **types;
9866                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9867                 int i, count;
9868
9869                 count = mono_array_length (gclass->type_arguments);
9870                 types = g_new0 (MonoType*, count);
9871                 for (i = 0; i < count; ++i) {
9872                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9873                         types [i] = mono_reflection_type_get_handle (t);
9874                         if (!types[i]) {
9875                                 g_free (types);
9876                                 return NULL;
9877                         }
9878                 }
9879
9880                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9881                 g_free (types);
9882                 g_assert (res);
9883                 gclass->type.type = res;
9884                 return res;
9885         }
9886
9887         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9888         return NULL;
9889 }
9890
9891
9892
9893 void
9894 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9895 {
9896         mono_reflection_type_get_handle (type);
9897 }
9898
9899 void
9900 mono_reflection_register_with_runtime (MonoReflectionType *type)
9901 {
9902         MonoType *res = mono_reflection_type_get_handle (type);
9903         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9904         MonoClass *klass;
9905
9906         if (!res)
9907                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9908
9909         klass = mono_class_from_mono_type (res);
9910
9911         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9912         mono_domain_lock (domain);
9913
9914         if (!image_is_dynamic (klass->image)) {
9915                 mono_class_setup_supertypes (klass);
9916         } else {
9917                 if (!domain->type_hash)
9918                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9919                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9920                 mono_g_hash_table_insert (domain->type_hash, res, type);
9921         }
9922         mono_domain_unlock (domain);
9923         mono_loader_unlock ();
9924 }
9925
9926 /**
9927  * LOCKING: Assumes the loader lock is held.
9928  */
9929 static MonoMethodSignature*
9930 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9931         MonoMethodSignature *sig;
9932         int count, i;
9933
9934         count = parameters? mono_array_length (parameters): 0;
9935
9936         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9937         sig->param_count = count;
9938         sig->sentinelpos = -1; /* FIXME */
9939         for (i = 0; i < count; ++i)
9940                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9941         return sig;
9942 }
9943
9944 /**
9945  * LOCKING: Assumes the loader lock is held.
9946  */
9947 static MonoMethodSignature*
9948 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9949         MonoMethodSignature *sig;
9950
9951         sig = parameters_to_signature (image, ctor->parameters);
9952         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9953         sig->ret = &mono_defaults.void_class->byval_arg;
9954         return sig;
9955 }
9956
9957 /**
9958  * LOCKING: Assumes the loader lock is held.
9959  */
9960 static MonoMethodSignature*
9961 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9962         MonoMethodSignature *sig;
9963
9964         sig = parameters_to_signature (image, method->parameters);
9965         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9966         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9967         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9968         return sig;
9969 }
9970
9971 static MonoMethodSignature*
9972 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9973         MonoMethodSignature *sig;
9974
9975         sig = parameters_to_signature (NULL, method->parameters);
9976         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9977         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9978         sig->generic_param_count = 0;
9979         return sig;
9980 }
9981
9982 static void
9983 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9984 {
9985         MonoClass *klass = mono_object_class (prop);
9986         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9987                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9988                 *name = mono_string_to_utf8 (pb->name);
9989                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9990         } else {
9991                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9992                 *name = g_strdup (p->property->name);
9993                 if (p->property->get)
9994                         *type = mono_method_signature (p->property->get)->ret;
9995                 else
9996                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9997         }
9998 }
9999
10000 static void
10001 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10002 {
10003         MonoClass *klass = mono_object_class (field);
10004         if (strcmp (klass->name, "FieldBuilder") == 0) {
10005                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10006                 *name = mono_string_to_utf8 (fb->name);
10007                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10008         } else {
10009                 MonoReflectionField *f = (MonoReflectionField *)field;
10010                 *name = g_strdup (mono_field_get_name (f->field));
10011                 *type = f->field->type;
10012         }
10013 }
10014
10015 #else /* DISABLE_REFLECTION_EMIT */
10016
10017 void
10018 mono_reflection_register_with_runtime (MonoReflectionType *type)
10019 {
10020         /* This is empty */
10021 }
10022
10023 static gboolean
10024 is_sre_type_builder (MonoClass *klass)
10025 {
10026         return FALSE;
10027 }
10028
10029 static gboolean
10030 is_sre_generic_instance (MonoClass *klass)
10031 {
10032         return FALSE;
10033 }
10034
10035 static void
10036 init_type_builder_generics (MonoObject *type)
10037 {
10038 }
10039
10040 #endif /* !DISABLE_REFLECTION_EMIT */
10041
10042
10043 static gboolean
10044 is_sr_mono_field (MonoClass *klass)
10045 {
10046         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10047 }
10048
10049 static gboolean
10050 is_sr_mono_property (MonoClass *klass)
10051 {
10052         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10053 }
10054
10055 static gboolean
10056 is_sr_mono_method (MonoClass *klass)
10057 {
10058         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10059 }
10060
10061 static gboolean
10062 is_sr_mono_cmethod (MonoClass *klass)
10063 {
10064         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10065 }
10066
10067 static gboolean
10068 is_sr_mono_generic_method (MonoClass *klass)
10069 {
10070         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10071 }
10072
10073 static gboolean
10074 is_sr_mono_generic_cmethod (MonoClass *klass)
10075 {
10076         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10077 }
10078
10079 gboolean
10080 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10081 {
10082         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10083 }
10084
10085 static gboolean
10086 is_usertype (MonoReflectionType *ref)
10087 {
10088         MonoClass *klass = mono_object_class (ref);
10089         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10090 }
10091
10092 static MonoReflectionType*
10093 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10094 {
10095         mono_error_init (error);
10096         if (!type || type->type)
10097                 return type;
10098
10099         if (is_usertype (type)) {
10100                 type = mono_reflection_type_get_underlying_system_type (type);
10101                 if (is_usertype (type)) {
10102                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10103                         return NULL;
10104                 }
10105         }
10106
10107         return type;
10108 }
10109 /*
10110  * Encode a value in a custom attribute stream of bytes.
10111  * The value to encode is either supplied as an object in argument val
10112  * (valuetypes are boxed), or as a pointer to the data in the
10113  * argument argval.
10114  * @type represents the type of the value
10115  * @buffer is the start of the buffer
10116  * @p the current position in the buffer
10117  * @buflen contains the size of the buffer and is used to return the new buffer size
10118  * if this needs to be realloced.
10119  * @retbuffer and @retp return the start and the position of the buffer
10120  */
10121 static void
10122 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10123 {
10124         MonoTypeEnum simple_type;
10125         
10126         if ((p-buffer) + 10 >= *buflen) {
10127                 char *newbuf;
10128                 *buflen *= 2;
10129                 newbuf = (char *)g_realloc (buffer, *buflen);
10130                 p = newbuf + (p-buffer);
10131                 buffer = newbuf;
10132         }
10133         if (!argval)
10134                 argval = ((char*)arg + sizeof (MonoObject));
10135         simple_type = type->type;
10136 handle_enum:
10137         switch (simple_type) {
10138         case MONO_TYPE_BOOLEAN:
10139         case MONO_TYPE_U1:
10140         case MONO_TYPE_I1:
10141                 *p++ = *argval;
10142                 break;
10143         case MONO_TYPE_CHAR:
10144         case MONO_TYPE_U2:
10145         case MONO_TYPE_I2:
10146                 swap_with_size (p, argval, 2, 1);
10147                 p += 2;
10148                 break;
10149         case MONO_TYPE_U4:
10150         case MONO_TYPE_I4:
10151         case MONO_TYPE_R4:
10152                 swap_with_size (p, argval, 4, 1);
10153                 p += 4;
10154                 break;
10155         case MONO_TYPE_R8:
10156                 swap_with_size (p, argval, 8, 1);
10157                 p += 8;
10158                 break;
10159         case MONO_TYPE_U8:
10160         case MONO_TYPE_I8:
10161                 swap_with_size (p, argval, 8, 1);
10162                 p += 8;
10163                 break;
10164         case MONO_TYPE_VALUETYPE:
10165                 if (type->data.klass->enumtype) {
10166                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10167                         goto handle_enum;
10168                 } else {
10169                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10170                 }
10171                 break;
10172         case MONO_TYPE_STRING: {
10173                 char *str;
10174                 guint32 slen;
10175                 if (!arg) {
10176                         *p++ = 0xFF;
10177                         break;
10178                 }
10179                 str = mono_string_to_utf8 ((MonoString*)arg);
10180                 slen = strlen (str);
10181                 if ((p-buffer) + 10 + slen >= *buflen) {
10182                         char *newbuf;
10183                         *buflen *= 2;
10184                         *buflen += slen;
10185                         newbuf = (char *)g_realloc (buffer, *buflen);
10186                         p = newbuf + (p-buffer);
10187                         buffer = newbuf;
10188                 }
10189                 mono_metadata_encode_value (slen, p, &p);
10190                 memcpy (p, str, slen);
10191                 p += slen;
10192                 g_free (str);
10193                 break;
10194         }
10195         case MONO_TYPE_CLASS: {
10196                 char *str;
10197                 guint32 slen;
10198                 if (!arg) {
10199                         *p++ = 0xFF;
10200                         break;
10201                 }
10202 handle_type:
10203                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10204                 slen = strlen (str);
10205                 if ((p-buffer) + 10 + slen >= *buflen) {
10206                         char *newbuf;
10207                         *buflen *= 2;
10208                         *buflen += slen;
10209                         newbuf = (char *)g_realloc (buffer, *buflen);
10210                         p = newbuf + (p-buffer);
10211                         buffer = newbuf;
10212                 }
10213                 mono_metadata_encode_value (slen, p, &p);
10214                 memcpy (p, str, slen);
10215                 p += slen;
10216                 g_free (str);
10217                 break;
10218         }
10219         case MONO_TYPE_SZARRAY: {
10220                 int len, i;
10221                 MonoClass *eclass, *arg_eclass;
10222
10223                 if (!arg) {
10224                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10225                         break;
10226                 }
10227                 len = mono_array_length ((MonoArray*)arg);
10228                 *p++ = len & 0xff;
10229                 *p++ = (len >> 8) & 0xff;
10230                 *p++ = (len >> 16) & 0xff;
10231                 *p++ = (len >> 24) & 0xff;
10232                 *retp = p;
10233                 *retbuffer = buffer;
10234                 eclass = type->data.klass;
10235                 arg_eclass = mono_object_class (arg)->element_class;
10236
10237                 if (!eclass) {
10238                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10239                         eclass = mono_defaults.object_class;
10240                 }
10241                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10242                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10243                         int elsize = mono_class_array_element_size (arg_eclass);
10244                         for (i = 0; i < len; ++i) {
10245                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10246                                 elptr += elsize;
10247                         }
10248                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10249                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10250                         int elsize = mono_class_array_element_size (eclass);
10251                         for (i = 0; i < len; ++i) {
10252                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10253                                 elptr += elsize;
10254                         }
10255                 } else {
10256                         for (i = 0; i < len; ++i) {
10257                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10258                         }
10259                 }
10260                 break;
10261         }
10262         case MONO_TYPE_OBJECT: {
10263                 MonoClass *klass;
10264                 char *str;
10265                 guint32 slen;
10266
10267                 /*
10268                  * The parameter type is 'object' but the type of the actual
10269                  * argument is not. So we have to add type information to the blob
10270                  * too. This is completely undocumented in the spec.
10271                  */
10272
10273                 if (arg == NULL) {
10274                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10275                         *p++ = 0xFF;
10276                         break;
10277                 }
10278                 
10279                 klass = mono_object_class (arg);
10280
10281                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10282                         *p++ = 0x50;
10283                         goto handle_type;
10284                 } else if (klass->enumtype) {
10285                         *p++ = 0x55;
10286                 } else if (klass == mono_defaults.string_class) {
10287                         simple_type = MONO_TYPE_STRING;
10288                         *p++ = 0x0E;
10289                         goto handle_enum;
10290                 } else if (klass->rank == 1) {
10291                         *p++ = 0x1D;
10292                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10293                                 /* See Partition II, Appendix B3 */
10294                                 *p++ = 0x51;
10295                         else
10296                                 *p++ = klass->element_class->byval_arg.type;
10297                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10298                         break;
10299                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10300                         *p++ = simple_type = klass->byval_arg.type;
10301                         goto handle_enum;
10302                 } else {
10303                         g_error ("unhandled type in custom attr");
10304                 }
10305                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10306                 slen = strlen (str);
10307                 if ((p-buffer) + 10 + slen >= *buflen) {
10308                         char *newbuf;
10309                         *buflen *= 2;
10310                         *buflen += slen;
10311                         newbuf = (char *)g_realloc (buffer, *buflen);
10312                         p = newbuf + (p-buffer);
10313                         buffer = newbuf;
10314                 }
10315                 mono_metadata_encode_value (slen, p, &p);
10316                 memcpy (p, str, slen);
10317                 p += slen;
10318                 g_free (str);
10319                 simple_type = mono_class_enum_basetype (klass)->type;
10320                 goto handle_enum;
10321         }
10322         default:
10323                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10324         }
10325         *retp = p;
10326         *retbuffer = buffer;
10327 }
10328
10329 static void
10330 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10331 {
10332         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10333                 char *str = type_get_qualified_name (type, NULL);
10334                 int slen = strlen (str);
10335
10336                 *p++ = 0x55;
10337                 /*
10338                  * This seems to be optional...
10339                  * *p++ = 0x80;
10340                  */
10341                 mono_metadata_encode_value (slen, p, &p);
10342                 memcpy (p, str, slen);
10343                 p += slen;
10344                 g_free (str);
10345         } else if (type->type == MONO_TYPE_OBJECT) {
10346                 *p++ = 0x51;
10347         } else if (type->type == MONO_TYPE_CLASS) {
10348                 /* it should be a type: encode_cattr_value () has the check */
10349                 *p++ = 0x50;
10350         } else {
10351                 mono_metadata_encode_value (type->type, p, &p);
10352                 if (type->type == MONO_TYPE_SZARRAY)
10353                         /* See the examples in Partition VI, Annex B */
10354                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10355         }
10356
10357         *retp = p;
10358 }
10359
10360 #ifndef DISABLE_REFLECTION_EMIT
10361 static void
10362 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10363 {
10364         int len;
10365         /* Preallocate a large enough buffer */
10366         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10367                 char *str = type_get_qualified_name (type, NULL);
10368                 len = strlen (str);
10369                 g_free (str);
10370         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10371                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10372                 len = strlen (str);
10373                 g_free (str);
10374         } else {
10375                 len = 0;
10376         }
10377         len += strlen (name);
10378
10379         if ((p-buffer) + 20 + len >= *buflen) {
10380                 char *newbuf;
10381                 *buflen *= 2;
10382                 *buflen += len;
10383                 newbuf = (char *)g_realloc (buffer, *buflen);
10384                 p = newbuf + (p-buffer);
10385                 buffer = newbuf;
10386         }
10387
10388         encode_field_or_prop_type (type, p, &p);
10389
10390         len = strlen (name);
10391         mono_metadata_encode_value (len, p, &p);
10392         memcpy (p, name, len);
10393         p += len;
10394         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10395         *retp = p;
10396         *retbuffer = buffer;
10397 }
10398
10399 /*
10400  * mono_reflection_get_custom_attrs_blob:
10401  * @ctor: custom attribute constructor
10402  * @ctorArgs: arguments o the constructor
10403  * @properties:
10404  * @propValues:
10405  * @fields:
10406  * @fieldValues:
10407  * 
10408  * Creates the blob of data that needs to be saved in the metadata and that represents
10409  * the custom attributed described by @ctor, @ctorArgs etc.
10410  * Returns: a Byte array representing the blob of data.
10411  */
10412 MonoArray*
10413 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10414 {
10415         MonoArray *result;
10416         MonoMethodSignature *sig;
10417         MonoObject *arg;
10418         char *buffer, *p;
10419         guint32 buflen, i;
10420
10421         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10422                 /* sig is freed later so allocate it in the heap */
10423                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10424         } else {
10425                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10426         }
10427
10428         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10429         buflen = 256;
10430         p = buffer = (char *)g_malloc (buflen);
10431         /* write the prolog */
10432         *p++ = 1;
10433         *p++ = 0;
10434         for (i = 0; i < sig->param_count; ++i) {
10435                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10436                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10437         }
10438         i = 0;
10439         if (properties)
10440                 i += mono_array_length (properties);
10441         if (fields)
10442                 i += mono_array_length (fields);
10443         *p++ = i & 0xff;
10444         *p++ = (i >> 8) & 0xff;
10445         if (properties) {
10446                 MonoObject *prop;
10447                 for (i = 0; i < mono_array_length (properties); ++i) {
10448                         MonoType *ptype;
10449                         char *pname;
10450
10451                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10452                         get_prop_name_and_type (prop, &pname, &ptype);
10453                         *p++ = 0x54; /* PROPERTY signature */
10454                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10455                         g_free (pname);
10456                 }
10457         }
10458
10459         if (fields) {
10460                 MonoObject *field;
10461                 for (i = 0; i < mono_array_length (fields); ++i) {
10462                         MonoType *ftype;
10463                         char *fname;
10464
10465                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10466                         get_field_name_and_type (field, &fname, &ftype);
10467                         *p++ = 0x53; /* FIELD signature */
10468                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10469                         g_free (fname);
10470                 }
10471         }
10472
10473         g_assert (p - buffer <= buflen);
10474         buflen = p - buffer;
10475         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10476         p = mono_array_addr (result, char, 0);
10477         memcpy (p, buffer, buflen);
10478         g_free (buffer);
10479         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10480                 g_free (sig);
10481         return result;
10482 }
10483
10484 /*
10485  * mono_reflection_setup_internal_class:
10486  * @tb: a TypeBuilder object
10487  *
10488  * Creates a MonoClass that represents the TypeBuilder.
10489  * This is a trick that lets us simplify a lot of reflection code
10490  * (and will allow us to support Build and Run assemblies easier).
10491  */
10492 void
10493 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10494 {
10495         MonoError error;
10496         MonoClass *klass, *parent;
10497
10498         RESOLVE_TYPE (tb->parent, &error);
10499         mono_error_raise_exception (&error); /* FIXME don't raise here */
10500
10501         mono_loader_lock ();
10502
10503         if (tb->parent) {
10504                 /* check so we can compile corlib correctly */
10505                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10506                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10507                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10508                 } else {
10509                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10510                 }
10511         } else {
10512                 parent = NULL;
10513         }
10514         
10515         /* the type has already being created: it means we just have to change the parent */
10516         if (tb->type.type) {
10517                 klass = mono_class_from_mono_type (tb->type.type);
10518                 klass->parent = NULL;
10519                 /* fool mono_class_setup_parent */
10520                 klass->supertypes = NULL;
10521                 mono_class_setup_parent (klass, parent);
10522                 mono_class_setup_mono_type (klass);
10523                 mono_loader_unlock ();
10524                 return;
10525         }
10526
10527         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10528
10529         klass->image = &tb->module->dynamic_image->image;
10530
10531         klass->inited = 1; /* we lie to the runtime */
10532         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10533         if (!mono_error_ok (&error))
10534                 goto failure;
10535         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10536         if (!mono_error_ok (&error))
10537                 goto failure;
10538         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10539         klass->flags = tb->attrs;
10540         
10541         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10542
10543         klass->element_class = klass;
10544
10545         if (mono_class_get_ref_info (klass) == NULL) {
10546
10547                 mono_class_set_ref_info (klass, tb);
10548
10549                 /* Put into cache so mono_class_get_checked () will find it.
10550                 Skip nested types as those should not be available on the global scope. */
10551                 if (!tb->nesting_type)
10552                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10553
10554                 /*
10555                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10556                 by performing a mono_class_get which does the full resolution.
10557
10558                 Working around this semantics would require us to write a lot of code for no clear advantage.
10559                 */
10560                 mono_image_append_class_to_reflection_info_set (klass);
10561         } else {
10562                 g_assert (mono_class_get_ref_info (klass) == tb);
10563         }
10564
10565         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10566
10567         if (parent != NULL) {
10568                 mono_class_setup_parent (klass, parent);
10569         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10570                 const char *old_n = klass->name;
10571                 /* trick to get relative numbering right when compiling corlib */
10572                 klass->name = "BuildingObject";
10573                 mono_class_setup_parent (klass, mono_defaults.object_class);
10574                 klass->name = old_n;
10575         }
10576
10577         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10578                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10579                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10580                 klass->instance_size = sizeof (MonoObject);
10581                 klass->size_inited = 1;
10582                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10583         }
10584
10585         mono_class_setup_mono_type (klass);
10586
10587         mono_class_setup_supertypes (klass);
10588
10589         /*
10590          * FIXME: handle interfaces.
10591          */
10592
10593         tb->type.type = &klass->byval_arg;
10594
10595         if (tb->nesting_type) {
10596                 g_assert (tb->nesting_type->type);
10597                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10598         }
10599
10600         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10601
10602         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10603         
10604         mono_loader_unlock ();
10605         return;
10606
10607 failure:
10608         mono_loader_unlock ();
10609         mono_error_raise_exception (&error);
10610 }
10611
10612 /*
10613  * mono_reflection_setup_generic_class:
10614  * @tb: a TypeBuilder object
10615  *
10616  * Setup the generic class before adding the first generic parameter.
10617  */
10618 void
10619 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10620 {
10621 }
10622
10623 /*
10624  * mono_reflection_create_generic_class:
10625  * @tb: a TypeBuilder object
10626  *
10627  * Creates the generic class after all generic parameters have been added.
10628  */
10629 void
10630 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10631 {
10632         MonoClass *klass;
10633         int count, i;
10634
10635         klass = mono_class_from_mono_type (tb->type.type);
10636
10637         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10638
10639         if (klass->generic_container || (count == 0))
10640                 return;
10641
10642         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10643
10644         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10645
10646         klass->generic_container->owner.klass = klass;
10647         klass->generic_container->type_argc = count;
10648         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10649
10650         klass->is_generic = 1;
10651
10652         for (i = 0; i < count; i++) {
10653                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10654                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10655                 klass->generic_container->type_params [i] = *param;
10656                 /*Make sure we are a diferent type instance */
10657                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10658                 klass->generic_container->type_params [i].info.pklass = NULL;
10659                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10660
10661                 g_assert (klass->generic_container->type_params [i].param.owner);
10662         }
10663
10664         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10665 }
10666
10667 /*
10668  * mono_reflection_create_internal_class:
10669  * @tb: a TypeBuilder object
10670  *
10671  * Actually create the MonoClass that is associated with the TypeBuilder.
10672  */
10673 void
10674 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10675 {
10676         MonoClass *klass;
10677
10678         klass = mono_class_from_mono_type (tb->type.type);
10679
10680         mono_loader_lock ();
10681         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10682                 MonoReflectionFieldBuilder *fb;
10683                 MonoClass *ec;
10684                 MonoType *enum_basetype;
10685
10686                 g_assert (tb->fields != NULL);
10687                 g_assert (mono_array_length (tb->fields) >= 1);
10688
10689                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10690
10691                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10692                         mono_loader_unlock ();
10693                         return;
10694                 }
10695
10696                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10697                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10698                 if (!klass->element_class)
10699                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10700
10701                 /*
10702                  * get the element_class from the current corlib.
10703                  */
10704                 ec = default_class_from_mono_type (enum_basetype);
10705                 klass->instance_size = ec->instance_size;
10706                 klass->size_inited = 1;
10707                 /* 
10708                  * this is almost safe to do with enums and it's needed to be able
10709                  * to create objects of the enum type (for use in SetConstant).
10710                  */
10711                 /* FIXME: Does this mean enums can't have method overrides ? */
10712                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10713         }
10714         mono_loader_unlock ();
10715 }
10716
10717 static MonoMarshalSpec*
10718 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10719                                                                 MonoReflectionMarshal *minfo)
10720 {
10721         MonoMarshalSpec *res;
10722
10723         res = image_g_new0 (image, MonoMarshalSpec, 1);
10724         res->native = (MonoMarshalNative)minfo->type;
10725
10726         switch (minfo->type) {
10727         case MONO_NATIVE_LPARRAY:
10728                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10729                 if (minfo->has_size) {
10730                         res->data.array_data.param_num = minfo->param_num;
10731                         res->data.array_data.num_elem = minfo->count;
10732                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10733                 }
10734                 else {
10735                         res->data.array_data.param_num = -1;
10736                         res->data.array_data.num_elem = -1;
10737                         res->data.array_data.elem_mult = -1;
10738                 }
10739                 break;
10740
10741         case MONO_NATIVE_BYVALTSTR:
10742         case MONO_NATIVE_BYVALARRAY:
10743                 res->data.array_data.num_elem = minfo->count;
10744                 break;
10745
10746         case MONO_NATIVE_CUSTOM:
10747                 if (minfo->marshaltyperef)
10748                         res->data.custom_data.custom_name =
10749                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10750                 if (minfo->mcookie)
10751                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10752                 break;
10753
10754         default:
10755                 break;
10756         }
10757
10758         return res;
10759 }
10760 #endif /* !DISABLE_REFLECTION_EMIT */
10761
10762 MonoReflectionMarshalAsAttribute*
10763 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10764                                                                                    MonoMarshalSpec *spec)
10765 {
10766         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10767         MonoError error;
10768         MonoReflectionType *rt;
10769         MonoReflectionMarshalAsAttribute *minfo;
10770         MonoType *mtype;
10771
10772         if (!System_Reflection_Emit_MarshalAsAttribute) {
10773                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10774                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10775                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10776         }
10777
10778         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10779         mono_error_raise_exception (&error); /* FIXME don't raise here */
10780         minfo->utype = spec->native;
10781
10782         switch (minfo->utype) {
10783         case MONO_NATIVE_LPARRAY:
10784                 minfo->array_subtype = spec->data.array_data.elem_type;
10785                 minfo->size_const = spec->data.array_data.num_elem;
10786                 if (spec->data.array_data.param_num != -1)
10787                         minfo->size_param_index = spec->data.array_data.param_num;
10788                 break;
10789
10790         case MONO_NATIVE_BYVALTSTR:
10791         case MONO_NATIVE_BYVALARRAY:
10792                 minfo->size_const = spec->data.array_data.num_elem;
10793                 break;
10794
10795         case MONO_NATIVE_CUSTOM:
10796                 if (spec->data.custom_data.custom_name) {
10797                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10798                         if (mtype) {
10799                                 rt = mono_type_get_object_checked (domain, mtype, &error);
10800                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10801
10802                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10803                         }
10804
10805                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10806                 }
10807                 if (spec->data.custom_data.cookie)
10808                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10809                 break;
10810
10811         default:
10812                 break;
10813         }
10814
10815         return minfo;
10816 }
10817
10818 #ifndef DISABLE_REFLECTION_EMIT
10819 static MonoMethod*
10820 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10821                                          ReflectionMethodBuilder *rmb,
10822                                          MonoMethodSignature *sig)
10823 {
10824         MonoError error;
10825         MonoMethod *m;
10826         MonoMethodWrapper *wrapperm;
10827         MonoMarshalSpec **specs;
10828         MonoReflectionMethodAux *method_aux;
10829         MonoImage *image;
10830         gboolean dynamic;
10831         int i;
10832
10833         mono_error_init (&error);
10834         /*
10835          * Methods created using a MethodBuilder should have their memory allocated
10836          * inside the image mempool, while dynamic methods should have their memory
10837          * malloc'd.
10838          */
10839         dynamic = rmb->refs != NULL;
10840         image = dynamic ? NULL : klass->image;
10841
10842         if (!dynamic)
10843                 g_assert (!klass->generic_class);
10844
10845         mono_loader_lock ();
10846
10847         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10848                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10849                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10850         else
10851                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10852
10853         wrapperm = (MonoMethodWrapper*)m;
10854
10855         m->dynamic = dynamic;
10856         m->slot = -1;
10857         m->flags = rmb->attrs;
10858         m->iflags = rmb->iattrs;
10859         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10860         m->klass = klass;
10861         m->signature = sig;
10862         m->sre_method = TRUE;
10863         m->skip_visibility = rmb->skip_visibility;
10864         if (rmb->table_idx)
10865                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10866
10867         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10868                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10869                         m->string_ctor = 1;
10870
10871                 m->signature->pinvoke = 1;
10872         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10873                 m->signature->pinvoke = 1;
10874
10875                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10876
10877                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10878                 g_assert (mono_error_ok (&error));
10879                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10880                 g_assert (mono_error_ok (&error));
10881                 
10882                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10883
10884                 if (image_is_dynamic (klass->image))
10885                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10886
10887                 mono_loader_unlock ();
10888
10889                 return m;
10890         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10891                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10892                 MonoMethodHeader *header;
10893                 guint32 code_size;
10894                 gint32 max_stack, i;
10895                 gint32 num_locals = 0;
10896                 gint32 num_clauses = 0;
10897                 guint8 *code;
10898
10899                 if (rmb->ilgen) {
10900                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10901                         code_size = rmb->ilgen->code_len;
10902                         max_stack = rmb->ilgen->max_stack;
10903                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10904                         if (rmb->ilgen->ex_handlers)
10905                                 num_clauses = method_count_clauses (rmb->ilgen);
10906                 } else {
10907                         if (rmb->code) {
10908                                 code = mono_array_addr (rmb->code, guint8, 0);
10909                                 code_size = mono_array_length (rmb->code);
10910                                 /* we probably need to run a verifier on the code... */
10911                                 max_stack = 8; 
10912                         }
10913                         else {
10914                                 code = NULL;
10915                                 code_size = 0;
10916                                 max_stack = 8;
10917                         }
10918                 }
10919
10920                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10921                 header->code_size = code_size;
10922                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10923                 memcpy ((char*)header->code, code, code_size);
10924                 header->max_stack = max_stack;
10925                 header->init_locals = rmb->init_locals;
10926                 header->num_locals = num_locals;
10927
10928                 for (i = 0; i < num_locals; ++i) {
10929                         MonoReflectionLocalBuilder *lb = 
10930                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10931
10932                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10933                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10934                 }
10935
10936                 header->num_clauses = num_clauses;
10937                 if (num_clauses) {
10938                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10939                                  rmb->ilgen, num_clauses);
10940                 }
10941
10942                 wrapperm->header = header;
10943         }
10944
10945         if (rmb->generic_params) {
10946                 int count = mono_array_length (rmb->generic_params);
10947                 MonoGenericContainer *container = rmb->generic_container;
10948
10949                 g_assert (container);
10950
10951                 container->type_argc = count;
10952                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10953                 container->owner.method = m;
10954                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10955
10956                 m->is_generic = TRUE;
10957                 mono_method_set_generic_container (m, container);
10958
10959                 for (i = 0; i < count; i++) {
10960                         MonoReflectionGenericParam *gp =
10961                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10962                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10963                         container->type_params [i] = *param;
10964                 }
10965
10966                 /*
10967                  * The method signature might have pointers to generic parameters that belong to other methods.
10968                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10969                  * generic parameters.
10970                  */
10971                 for (i = 0; i < m->signature->param_count; ++i) {
10972                         MonoType *t = m->signature->params [i];
10973                         if (t->type == MONO_TYPE_MVAR) {
10974                                 MonoGenericParam *gparam =  t->data.generic_param;
10975                                 if (gparam->num < count) {
10976                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10977                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10978                                 }
10979
10980                         }
10981                 }
10982
10983                 if (klass->generic_container) {
10984                         container->parent = klass->generic_container;
10985                         container->context.class_inst = klass->generic_container->context.class_inst;
10986                 }
10987                 container->context.method_inst = mono_get_shared_generic_inst (container);
10988         }
10989
10990         if (rmb->refs) {
10991                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10992                 int i;
10993                 void **data;
10994
10995                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10996
10997                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10998                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10999                 for (i = 0; i < rmb->nrefs; ++i)
11000                         data [i + 1] = rmb->refs [i];
11001         }
11002
11003         method_aux = NULL;
11004
11005         /* Parameter info */
11006         if (rmb->pinfo) {
11007                 if (!method_aux)
11008                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11009                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11010                 for (i = 0; i <= m->signature->param_count; ++i) {
11011                         MonoReflectionParamBuilder *pb;
11012                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11013                                 if ((i > 0) && (pb->attrs)) {
11014                                         /* Make a copy since it might point to a shared type structure */
11015                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11016                                         m->signature->params [i - 1]->attrs = pb->attrs;
11017                                 }
11018
11019                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11020                                         MonoDynamicImage *assembly;
11021                                         guint32 idx, len;
11022                                         MonoTypeEnum def_type;
11023                                         char *p;
11024                                         const char *p2;
11025
11026                                         if (!method_aux->param_defaults) {
11027                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11028                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11029                                         }
11030                                         assembly = (MonoDynamicImage*)klass->image;
11031                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11032                                         /* Copy the data from the blob since it might get realloc-ed */
11033                                         p = assembly->blob.data + idx;
11034                                         len = mono_metadata_decode_blob_size (p, &p2);
11035                                         len += p2 - p;
11036                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11037                                         method_aux->param_default_types [i] = def_type;
11038                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11039                                 }
11040
11041                                 if (pb->name) {
11042                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11043                                         g_assert (mono_error_ok (&error));
11044                                 }
11045                                 if (pb->cattrs) {
11046                                         if (!method_aux->param_cattr)
11047                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11048                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11049                                 }
11050                         }
11051                 }
11052         }
11053
11054         /* Parameter marshalling */
11055         specs = NULL;
11056         if (rmb->pinfo)         
11057                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11058                         MonoReflectionParamBuilder *pb;
11059                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11060                                 if (pb->marshal_info) {
11061                                         if (specs == NULL)
11062                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11063                                         specs [pb->position] = 
11064                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11065                                 }
11066                         }
11067                 }
11068         if (specs != NULL) {
11069                 if (!method_aux)
11070                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11071                 method_aux->param_marshall = specs;
11072         }
11073
11074         if (image_is_dynamic (klass->image) && method_aux)
11075                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11076
11077         mono_loader_unlock ();
11078
11079         return m;
11080 }       
11081
11082 static MonoMethod*
11083 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11084 {
11085         ReflectionMethodBuilder rmb;
11086         MonoMethodSignature *sig;
11087
11088         mono_loader_lock ();
11089         sig = ctor_builder_to_signature (klass->image, mb);
11090         mono_loader_unlock ();
11091
11092         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11093
11094         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11095         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11096
11097         /* If we are in a generic class, we might be called multiple times from inflate_method */
11098         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11099                 /* ilgen is no longer needed */
11100                 mb->ilgen = NULL;
11101         }
11102
11103         return mb->mhandle;
11104 }
11105
11106 static MonoMethod*
11107 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11108 {
11109         ReflectionMethodBuilder rmb;
11110         MonoMethodSignature *sig;
11111
11112         mono_loader_lock ();
11113         sig = method_builder_to_signature (klass->image, mb);
11114         mono_loader_unlock ();
11115
11116         reflection_methodbuilder_from_method_builder (&rmb, mb);
11117
11118         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11119         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11120
11121         /* If we are in a generic class, we might be called multiple times from inflate_method */
11122         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11123                 /* ilgen is no longer needed */
11124                 mb->ilgen = NULL;
11125         }
11126         return mb->mhandle;
11127 }
11128
11129 static MonoClassField*
11130 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11131 {
11132         MonoClassField *field;
11133         MonoType *custom;
11134         MonoError error;
11135
11136         field = g_new0 (MonoClassField, 1);
11137
11138         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11139         g_assert (mono_error_ok (&error));
11140         if (fb->attrs || fb->modreq || fb->modopt) {
11141                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11142                 field->type->attrs = fb->attrs;
11143
11144                 g_assert (image_is_dynamic (klass->image));
11145                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11146                 g_free (field->type);
11147                 field->type = mono_metadata_type_dup (klass->image, custom);
11148                 g_free (custom);
11149         } else {
11150                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11151         }
11152         if (fb->offset != -1)
11153                 field->offset = fb->offset;
11154         field->parent = klass;
11155         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11156
11157         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11158
11159         return field;
11160 }
11161 #endif
11162
11163 MonoType*
11164 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11165 {
11166         MonoClass *klass;
11167         MonoReflectionTypeBuilder *tb = NULL;
11168         gboolean is_dynamic = FALSE;
11169         MonoClass *geninst;
11170
11171         mono_loader_lock ();
11172
11173         if (is_sre_type_builder (mono_object_class (type))) {
11174                 tb = (MonoReflectionTypeBuilder *) type;
11175
11176                 is_dynamic = TRUE;
11177         } else if (is_sre_generic_instance (mono_object_class (type))) {
11178                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11179                 MonoReflectionType *gtd = rgi->generic_type;
11180
11181                 if (is_sre_type_builder (mono_object_class (gtd))) {
11182                         tb = (MonoReflectionTypeBuilder *)gtd;
11183                         is_dynamic = TRUE;
11184                 }
11185         }
11186
11187         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11188         if (tb && tb->generic_container)
11189                 mono_reflection_create_generic_class (tb);
11190
11191         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11192         if (!klass->generic_container) {
11193                 mono_loader_unlock ();
11194                 return NULL;
11195         }
11196
11197         if (klass->wastypebuilder) {
11198                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11199
11200                 is_dynamic = TRUE;
11201         }
11202
11203         mono_loader_unlock ();
11204
11205         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11206
11207         return &geninst->byval_arg;
11208 }
11209
11210 MonoClass*
11211 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11212 {
11213         MonoGenericClass *gclass;
11214         MonoGenericInst *inst;
11215
11216         g_assert (klass->generic_container);
11217
11218         inst = mono_metadata_get_generic_inst (type_argc, types);
11219         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11220
11221         return mono_generic_class_get_class (gclass);
11222 }
11223
11224 MonoReflectionMethod*
11225 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11226 {
11227         MonoError error;
11228         MonoClass *klass;
11229         MonoMethod *method, *inflated;
11230         MonoMethodInflated *imethod;
11231         MonoGenericContext tmp_context;
11232         MonoGenericInst *ginst;
11233         MonoType **type_argv;
11234         int count, i;
11235
11236         /*FIXME but this no longer should happen*/
11237         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11238 #ifndef DISABLE_REFLECTION_EMIT
11239                 MonoReflectionMethodBuilder *mb = NULL;
11240                 MonoReflectionTypeBuilder *tb;
11241                 MonoClass *klass;
11242
11243                 mb = (MonoReflectionMethodBuilder *) rmethod;
11244                 tb = (MonoReflectionTypeBuilder *) mb->type;
11245                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11246
11247                 method = methodbuilder_to_mono_method (klass, mb);
11248 #else
11249                 g_assert_not_reached ();
11250                 method = NULL;
11251 #endif
11252         } else {
11253                 method = rmethod->method;
11254         }
11255
11256         klass = method->klass;
11257
11258         if (method->is_inflated)
11259                 method = ((MonoMethodInflated *) method)->declaring;
11260
11261         count = mono_method_signature (method)->generic_param_count;
11262         if (count != mono_array_length (types))
11263                 return NULL;
11264
11265         type_argv = g_new0 (MonoType *, count);
11266         for (i = 0; i < count; i++) {
11267                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11268                 type_argv [i] = mono_reflection_type_get_handle (garg);
11269         }
11270         ginst = mono_metadata_get_generic_inst (count, type_argv);
11271         g_free (type_argv);
11272
11273         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11274         tmp_context.method_inst = ginst;
11275
11276         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11277         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11278         imethod = (MonoMethodInflated *) inflated;
11279
11280         /*FIXME but I think this is no longer necessary*/
11281         if (image_is_dynamic (method->klass->image)) {
11282                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11283                 /*
11284                  * This table maps metadata structures representing inflated methods/fields
11285                  * to the reflection objects representing their generic definitions.
11286                  */
11287                 mono_image_lock ((MonoImage*)image);
11288                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11289                 mono_image_unlock ((MonoImage*)image);
11290         }
11291
11292         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11293                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11294         
11295         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11296         mono_error_raise_exception (&error); /* FIXME don't raise here */
11297         return ret;
11298 }
11299
11300 #ifndef DISABLE_REFLECTION_EMIT
11301
11302 static MonoMethod *
11303 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11304 {
11305         MonoMethodInflated *imethod;
11306         MonoGenericContext *context;
11307         int i;
11308
11309         /*
11310          * With generic code sharing the klass might not be inflated.
11311          * This can happen because classes inflated with their own
11312          * type arguments are "normalized" to the uninflated class.
11313          */
11314         if (!klass->generic_class)
11315                 return method;
11316
11317         context = mono_class_get_context (klass);
11318
11319         if (klass->method.count && klass->methods) {
11320                 /* Find the already created inflated method */
11321                 for (i = 0; i < klass->method.count; ++i) {
11322                         g_assert (klass->methods [i]->is_inflated);
11323                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11324                                 break;
11325                 }
11326                 g_assert (i < klass->method.count);
11327                 imethod = (MonoMethodInflated*)klass->methods [i];
11328         } else {
11329                 MonoError error;
11330                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11331                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11332         }
11333
11334         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11335                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11336
11337                 mono_image_lock ((MonoImage*)image);
11338                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11339                 mono_image_unlock ((MonoImage*)image);
11340         }
11341         return (MonoMethod *) imethod;
11342 }
11343
11344 static MonoMethod *
11345 inflate_method (MonoReflectionType *type, MonoObject *obj)
11346 {
11347         MonoMethod *method;
11348         MonoClass *gklass;
11349
11350         MonoClass *type_class = mono_object_class (type);
11351
11352         if (is_sre_generic_instance (type_class)) {
11353                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11354                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11355         } else if (is_sre_type_builder (type_class)) {
11356                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11357         } else if (type->type) {
11358                 gklass = mono_class_from_mono_type (type->type);
11359                 gklass = mono_class_get_generic_type_definition (gklass);
11360         } else {
11361                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11362         }
11363
11364         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11365                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11366                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11367                 else
11368                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11369         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11370                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11371         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11372                 method = ((MonoReflectionMethod *) obj)->method;
11373         else {
11374                 method = NULL; /* prevent compiler warning */
11375                 g_error ("can't handle type %s", obj->vtable->klass->name);
11376         }
11377
11378         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11379 }
11380
11381 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11382 void
11383 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11384 {
11385         MonoGenericClass *gclass;
11386         MonoDynamicGenericClass *dgclass;
11387         MonoClass *klass, *gklass;
11388         MonoType *gtype;
11389         int i;
11390
11391         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11392         klass = mono_class_from_mono_type (gtype);
11393         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11394         gclass = gtype->data.generic_class;
11395
11396         if (!gclass->is_dynamic)
11397                 return;
11398
11399         dgclass = (MonoDynamicGenericClass *) gclass;
11400
11401         if (dgclass->initialized)
11402                 return;
11403
11404         gklass = gclass->container_class;
11405         mono_class_init (gklass);
11406
11407         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11408
11409         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11410         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11411         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11412
11413         for (i = 0; i < dgclass->count_fields; i++) {
11414                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11415                 MonoClassField *field, *inflated_field = NULL;
11416
11417                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11418                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11419                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11420                         field = ((MonoReflectionField *) obj)->field;
11421                 else {
11422                         field = NULL; /* prevent compiler warning */
11423                         g_assert_not_reached ();
11424                 }
11425
11426                 dgclass->fields [i] = *field;
11427                 dgclass->fields [i].parent = klass;
11428                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11429                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11430                 dgclass->field_generic_types [i] = field->type;
11431                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11432                 dgclass->field_objects [i] = obj;
11433
11434                 if (inflated_field) {
11435                         g_free (inflated_field);
11436                 } else {
11437                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11438                 }
11439         }
11440
11441         dgclass->initialized = TRUE;
11442 }
11443
11444 void
11445 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11446 {
11447         MonoDynamicGenericClass *dgclass;
11448         int i;
11449
11450         g_assert (gclass->is_dynamic);
11451
11452         dgclass = (MonoDynamicGenericClass *)gclass;
11453
11454         for (i = 0; i < dgclass->count_fields; ++i) {
11455                 MonoClassField *field = dgclass->fields + i;
11456                 mono_metadata_free_type (field->type);
11457                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11458         }
11459 }
11460
11461 static void
11462 fix_partial_generic_class (MonoClass *klass)
11463 {
11464         MonoClass *gklass = klass->generic_class->container_class;
11465         MonoDynamicGenericClass *dgclass;
11466         int i;
11467
11468         if (klass->wastypebuilder)
11469                 return;
11470
11471         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11472         if (klass->parent != gklass->parent) {
11473                 MonoError error;
11474                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11475                 if (mono_error_ok (&error)) {
11476                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11477                         mono_metadata_free_type (parent_type);
11478                         if (parent != klass->parent) {
11479                                 /*fool mono_class_setup_parent*/
11480                                 klass->supertypes = NULL;
11481                                 mono_class_setup_parent (klass, parent);
11482                         }
11483                 } else {
11484                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11485                         mono_error_cleanup (&error);
11486                         if (gklass->wastypebuilder)
11487                                 klass->wastypebuilder = TRUE;
11488                         return;
11489                 }
11490         }
11491
11492         if (!dgclass->initialized)
11493                 return;
11494
11495         if (klass->method.count != gklass->method.count) {
11496                 klass->method.count = gklass->method.count;
11497                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11498
11499                 for (i = 0; i < klass->method.count; i++) {
11500                         MonoError error;
11501                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11502                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11503                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11504                 }
11505         }
11506
11507         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11508                 klass->interface_count = gklass->interface_count;
11509                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11510                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11511
11512                 for (i = 0; i < gklass->interface_count; ++i) {
11513                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11514                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11515                         mono_metadata_free_type (iface_type);
11516
11517                         ensure_runtime_vtable (klass->interfaces [i]);
11518                 }
11519                 klass->interfaces_inited = 1;
11520         }
11521
11522         if (klass->field.count != gklass->field.count) {
11523                 klass->field.count = gklass->field.count;
11524                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11525
11526                 for (i = 0; i < klass->field.count; i++) {
11527                         klass->fields [i] = gklass->fields [i];
11528                         klass->fields [i].parent = klass;
11529                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11530                 }
11531         }
11532
11533         /*We can only finish with this klass once it's parent has as well*/
11534         if (gklass->wastypebuilder)
11535                 klass->wastypebuilder = TRUE;
11536         return;
11537 }
11538
11539 static void
11540 ensure_generic_class_runtime_vtable (MonoClass *klass)
11541 {
11542         MonoClass *gklass = klass->generic_class->container_class;
11543
11544         ensure_runtime_vtable (gklass); 
11545
11546         fix_partial_generic_class (klass);
11547 }
11548
11549 static void
11550 ensure_runtime_vtable (MonoClass *klass)
11551 {
11552         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11553         int i, num, j;
11554
11555         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11556                 return;
11557         if (klass->parent)
11558                 ensure_runtime_vtable (klass->parent);
11559
11560         if (tb) {
11561                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11562                 num += tb->num_methods;
11563                 klass->method.count = num;
11564                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11565                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11566                 for (i = 0; i < num; ++i)
11567                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11568                 num = tb->num_methods;
11569                 j = i;
11570                 for (i = 0; i < num; ++i)
11571                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11572         
11573                 if (tb->interfaces) {
11574                         klass->interface_count = mono_array_length (tb->interfaces);
11575                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11576                         for (i = 0; i < klass->interface_count; ++i) {
11577                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11578                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11579                                 ensure_runtime_vtable (klass->interfaces [i]);
11580                         }
11581                         klass->interfaces_inited = 1;
11582                 }
11583         } else if (klass->generic_class){
11584                 ensure_generic_class_runtime_vtable (klass);
11585         }
11586
11587         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11588                 int slot_num = 0;
11589                 for (i = 0; i < klass->method.count; ++i) {
11590                         MonoMethod *im = klass->methods [i];
11591                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11592                                 im->slot = slot_num++;
11593                 }
11594                 
11595                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11596                 mono_class_setup_interface_offsets (klass);
11597                 mono_class_setup_interface_id (klass);
11598         }
11599
11600         /*
11601          * The generic vtable is needed even if image->run is not set since some
11602          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11603          * method->slot being defined.
11604          */
11605
11606         /* 
11607          * tb->methods could not be freed since it is used for determining 
11608          * overrides during dynamic vtable construction.
11609          */
11610 }
11611
11612 static MonoMethod*
11613 mono_reflection_method_get_handle (MonoObject *method)
11614 {
11615         MonoClass *klass = mono_object_class (method);
11616         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11617                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11618                 return sr_method->method;
11619         }
11620         if (is_sre_method_builder (klass)) {
11621                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11622                 return mb->mhandle;
11623         }
11624         if (is_sre_method_on_tb_inst (klass)) {
11625                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11626                 MonoMethod *result;
11627                 /*FIXME move this to a proper method and unify with resolve_object*/
11628                 if (m->method_args) {
11629                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11630                 } else {
11631                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11632                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11633                         MonoMethod *mono_method;
11634
11635                         if (is_sre_method_builder (mono_object_class (m->mb)))
11636                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11637                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11638                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11639                         else
11640                                 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)));
11641
11642                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11643                 }
11644                 return result;
11645         }
11646
11647         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11648         return NULL;
11649 }
11650
11651 void
11652 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11653 {
11654         MonoReflectionTypeBuilder *tb;
11655         int i, j, onum;
11656         MonoReflectionMethod *m;
11657
11658         *overrides = NULL;
11659         *num_overrides = 0;
11660
11661         g_assert (image_is_dynamic (klass->image));
11662
11663         if (!mono_class_get_ref_info (klass))
11664                 return;
11665
11666         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11667
11668         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11669
11670         onum = 0;
11671         if (tb->methods) {
11672                 for (i = 0; i < tb->num_methods; ++i) {
11673                         MonoReflectionMethodBuilder *mb = 
11674                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11675                         if (mb->override_methods)
11676                                 onum += mono_array_length (mb->override_methods);
11677                 }
11678         }
11679
11680         if (onum) {
11681                 *overrides = g_new0 (MonoMethod*, onum * 2);
11682
11683                 onum = 0;
11684                 for (i = 0; i < tb->num_methods; ++i) {
11685                         MonoReflectionMethodBuilder *mb = 
11686                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11687                         if (mb->override_methods) {
11688                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11689                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11690
11691                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11692                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11693
11694                                         g_assert (mb->mhandle);
11695
11696                                         onum ++;
11697                                 }
11698                         }
11699                 }
11700         }
11701
11702         *num_overrides = onum;
11703 }
11704
11705 static void
11706 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11707 {
11708         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11709         MonoReflectionFieldBuilder *fb;
11710         MonoClassField *field;
11711         MonoImage *image = klass->image;
11712         const char *p, *p2;
11713         int i;
11714         guint32 len, idx, real_size = 0;
11715
11716         klass->field.count = tb->num_fields;
11717         klass->field.first = 0;
11718
11719         mono_error_init (error);
11720
11721         if (tb->class_size) {
11722                 if ((tb->packing_size & 0xffffff00) != 0) {
11723                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11724                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11725                         return;
11726                 }
11727                 klass->packing_size = tb->packing_size;
11728                 real_size = klass->instance_size + tb->class_size;
11729         }
11730
11731         if (!klass->field.count) {
11732                 klass->instance_size = MAX (klass->instance_size, real_size);
11733                 return;
11734         }
11735         
11736         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11737         mono_class_alloc_ext (klass);
11738         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11739         /*
11740         This is, guess what, a hack.
11741         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11742         On the static path no field class is resolved, only types are built. This is the right thing to do
11743         but we suck.
11744         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11745         */
11746         klass->size_inited = 1;
11747
11748         for (i = 0; i < klass->field.count; ++i) {
11749                 MonoArray *rva_data;
11750                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11751                 field = &klass->fields [i];
11752                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11753                 if (!mono_error_ok (error))
11754                         return;
11755                 if (fb->attrs) {
11756                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11757                         field->type->attrs = fb->attrs;
11758                 } else {
11759                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11760                 }
11761
11762                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11763                         char *base = mono_array_addr (rva_data, char, 0);
11764                         size_t size = mono_array_length (rva_data);
11765                         char *data = (char *)mono_image_alloc (klass->image, size);
11766                         memcpy (data, base, size);
11767                         klass->ext->field_def_values [i].data = data;
11768                 }
11769                 if (fb->offset != -1)
11770                         field->offset = fb->offset;
11771                 field->parent = klass;
11772                 fb->handle = field;
11773                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11774
11775                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11776                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11777                 }
11778                 if (fb->def_value) {
11779                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11780                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11781                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11782                         /* Copy the data from the blob since it might get realloc-ed */
11783                         p = assembly->blob.data + idx;
11784                         len = mono_metadata_decode_blob_size (p, &p2);
11785                         len += p2 - p;
11786                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11787                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11788                 }
11789         }
11790
11791         klass->instance_size = MAX (klass->instance_size, real_size);
11792         mono_class_layout_fields (klass);
11793 }
11794
11795 static void
11796 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11797 {
11798         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11799         MonoReflectionPropertyBuilder *pb;
11800         MonoImage *image = klass->image;
11801         MonoProperty *properties;
11802         int i;
11803
11804         mono_error_init (error);
11805
11806         if (!klass->ext)
11807                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11808
11809         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11810         klass->ext->property.first = 0;
11811
11812         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11813         klass->ext->properties = properties;
11814         for (i = 0; i < klass->ext->property.count; ++i) {
11815                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11816                 properties [i].parent = klass;
11817                 properties [i].attrs = pb->attrs;
11818                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11819                 if (!mono_error_ok (error))
11820                         return;
11821                 if (pb->get_method)
11822                         properties [i].get = pb->get_method->mhandle;
11823                 if (pb->set_method)
11824                         properties [i].set = pb->set_method->mhandle;
11825
11826                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11827                 if (pb->def_value) {
11828                         guint32 len, idx;
11829                         const char *p, *p2;
11830                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11831                         if (!klass->ext->prop_def_values)
11832                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11833                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11834                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11835                         /* Copy the data from the blob since it might get realloc-ed */
11836                         p = assembly->blob.data + idx;
11837                         len = mono_metadata_decode_blob_size (p, &p2);
11838                         len += p2 - p;
11839                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11840                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11841                 }
11842         }
11843 }
11844
11845 MonoReflectionEvent *
11846 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11847 {
11848         MonoEvent *event = g_new0 (MonoEvent, 1);
11849         MonoClass *klass;
11850
11851         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11852
11853         event->parent = klass;
11854         event->attrs = eb->attrs;
11855         event->name = mono_string_to_utf8 (eb->name);
11856         if (eb->add_method)
11857                 event->add = eb->add_method->mhandle;
11858         if (eb->remove_method)
11859                 event->remove = eb->remove_method->mhandle;
11860         if (eb->raise_method)
11861                 event->raise = eb->raise_method->mhandle;
11862
11863 #ifndef MONO_SMALL_CONFIG
11864         if (eb->other_methods) {
11865                 int j;
11866                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11867                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11868                         MonoReflectionMethodBuilder *mb = 
11869                                 mono_array_get (eb->other_methods,
11870                                                 MonoReflectionMethodBuilder*, j);
11871                         event->other [j] = mb->mhandle;
11872                 }
11873         }
11874 #endif
11875
11876         return mono_event_get_object (mono_object_domain (tb), klass, event);
11877 }
11878
11879 static void
11880 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11881 {
11882         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11883         MonoReflectionEventBuilder *eb;
11884         MonoImage *image = klass->image;
11885         MonoEvent *events;
11886         int i;
11887
11888         mono_error_init (error);
11889
11890         if (!klass->ext)
11891                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11892
11893         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11894         klass->ext->event.first = 0;
11895
11896         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11897         klass->ext->events = events;
11898         for (i = 0; i < klass->ext->event.count; ++i) {
11899                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11900                 events [i].parent = klass;
11901                 events [i].attrs = eb->attrs;
11902                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11903                 if (!mono_error_ok (error))
11904                         return;
11905                 if (eb->add_method)
11906                         events [i].add = eb->add_method->mhandle;
11907                 if (eb->remove_method)
11908                         events [i].remove = eb->remove_method->mhandle;
11909                 if (eb->raise_method)
11910                         events [i].raise = eb->raise_method->mhandle;
11911
11912 #ifndef MONO_SMALL_CONFIG
11913                 if (eb->other_methods) {
11914                         int j;
11915                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11916                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11917                                 MonoReflectionMethodBuilder *mb = 
11918                                         mono_array_get (eb->other_methods,
11919                                                                         MonoReflectionMethodBuilder*, j);
11920                                 events [i].other [j] = mb->mhandle;
11921                         }
11922                 }
11923 #endif
11924                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11925         }
11926 }
11927
11928 static gboolean
11929 remove_instantiations_of_and_ensure_contents (gpointer key,
11930                                                   gpointer value,
11931                                                   gpointer user_data)
11932 {
11933         MonoType *type = (MonoType*)key;
11934         MonoClass *klass = (MonoClass*)user_data;
11935
11936         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11937                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11938                 return TRUE;
11939         } else
11940                 return FALSE;
11941 }
11942
11943 static void
11944 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11945 {
11946         mono_error_init (error);
11947         int i;
11948
11949         if (!arr)
11950                 return;
11951
11952         for (i = 0; i < mono_array_length (arr); ++i) {
11953                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11954                 if (!mono_error_ok (error))
11955                         break;
11956         }
11957 }
11958
11959 MonoReflectionType*
11960 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11961 {
11962         MonoError error;
11963         MonoClass *klass;
11964         MonoDomain* domain;
11965         MonoReflectionType* res;
11966         int i, j;
11967
11968         domain = mono_object_domain (tb);
11969         klass = mono_class_from_mono_type (tb->type.type);
11970
11971         /*
11972          * Check for user defined Type subclasses.
11973          */
11974         RESOLVE_TYPE (tb->parent, &error);
11975         mono_error_raise_exception (&error); /* FIXME don't raise here */
11976         check_array_for_usertypes (tb->interfaces, &error);
11977         mono_error_raise_exception (&error); /*FIXME don't raise here */
11978         if (tb->fields) {
11979                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11980                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11981                         if (fb) {
11982                                 RESOLVE_TYPE (fb->type, &error);
11983                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11984                                 check_array_for_usertypes (fb->modreq, &error);
11985                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11986                                 check_array_for_usertypes (fb->modopt, &error);
11987                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11988                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11989                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11990                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11991                                 }
11992                         }
11993                 }
11994         }
11995         if (tb->methods) {
11996                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11997                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11998                         if (mb) {
11999                                 RESOLVE_TYPE (mb->rtype, &error);
12000                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12001                                 check_array_for_usertypes (mb->return_modreq, &error);
12002                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12003                                 check_array_for_usertypes (mb->return_modopt, &error);
12004                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12005                                 check_array_for_usertypes (mb->parameters, &error);
12006                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12007                                 if (mb->param_modreq)
12008                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12009                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12010                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12011                                         }
12012                                 if (mb->param_modopt)
12013                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12014                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12015                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12016                                         }
12017                         }
12018                 }
12019         }
12020         if (tb->ctors) {
12021                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12022                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12023                         if (mb) {
12024                                 check_array_for_usertypes (mb->parameters, &error);
12025                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12026                                 if (mb->param_modreq)
12027                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12028                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12029                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12030                                         }
12031                                 if (mb->param_modopt)
12032                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12033                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12034                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12035                                         }
12036                         }
12037                 }
12038         }
12039
12040         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12041
12042         /* 
12043          * we need to lock the domain because the lock will be taken inside
12044          * So, we need to keep the locking order correct.
12045          */
12046         mono_loader_lock ();
12047         mono_domain_lock (domain);
12048         if (klass->wastypebuilder) {
12049                 mono_domain_unlock (domain);
12050                 mono_loader_unlock ();
12051
12052                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12053                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12054
12055                 return res;
12056         }
12057         /*
12058          * Fields to set in klass:
12059          * the various flags: delegate/unicode/contextbound etc.
12060          */
12061         klass->flags = tb->attrs;
12062         klass->has_cctor = 1;
12063         klass->has_finalize = 1;
12064         klass->has_finalize_inited = 1;
12065
12066         mono_class_setup_parent (klass, klass->parent);
12067         /* fool mono_class_setup_supertypes */
12068         klass->supertypes = NULL;
12069         mono_class_setup_supertypes (klass);
12070         mono_class_setup_mono_type (klass);
12071
12072 #if 0
12073         if (!((MonoDynamicImage*)klass->image)->run) {
12074                 if (klass->generic_container) {
12075                         /* FIXME: The code below can't handle generic classes */
12076                         klass->wastypebuilder = TRUE;
12077                         mono_loader_unlock ();
12078                         mono_domain_unlock (domain);
12079
12080                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12081                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12082
12083                         return res;
12084                 }
12085         }
12086 #endif
12087
12088         /* enums are done right away */
12089         if (!klass->enumtype)
12090                 ensure_runtime_vtable (klass);
12091
12092         if (tb->subtypes) {
12093                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12094                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12095                         mono_class_alloc_ext (klass);
12096                         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)));
12097                 }
12098         }
12099
12100         klass->nested_classes_inited = TRUE;
12101
12102         /* fields and object layout */
12103         if (klass->parent) {
12104                 if (!klass->parent->size_inited)
12105                         mono_class_init (klass->parent);
12106                 klass->instance_size = klass->parent->instance_size;
12107                 klass->sizes.class_size = 0;
12108                 klass->min_align = klass->parent->min_align;
12109                 /* if the type has no fields we won't call the field_setup
12110                  * routine which sets up klass->has_references.
12111                  */
12112                 klass->has_references |= klass->parent->has_references;
12113         } else {
12114                 klass->instance_size = sizeof (MonoObject);
12115                 klass->min_align = 1;
12116         }
12117
12118         /* FIXME: handle packing_size and instance_size */
12119         typebuilder_setup_fields (klass, &error);
12120         if (!mono_error_ok (&error))
12121                 goto failure;
12122         typebuilder_setup_properties (klass, &error);
12123         if (!mono_error_ok (&error))
12124                 goto failure;
12125
12126         typebuilder_setup_events (klass, &error);
12127         if (!mono_error_ok (&error))
12128                 goto failure;
12129
12130         klass->wastypebuilder = TRUE;
12131
12132         /* 
12133          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12134          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12135          * we want to return normal System.MonoType objects, so clear these out from the cache.
12136          *
12137          * Together with this we must ensure the contents of all instances to match the created type.
12138          */
12139         if (domain->type_hash && klass->generic_container)
12140                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12141
12142         mono_domain_unlock (domain);
12143         mono_loader_unlock ();
12144
12145         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12146                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12147                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12148         }
12149
12150         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12151         mono_error_raise_exception (&error); /* FIXME don't raise here */
12152
12153         g_assert (res != (MonoReflectionType*)tb);
12154
12155         return res;
12156
12157 failure:
12158         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12159         klass->wastypebuilder = TRUE;
12160         mono_domain_unlock (domain);
12161         mono_loader_unlock ();
12162         mono_error_raise_exception (&error);
12163         return NULL;
12164 }
12165
12166 void
12167 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12168 {
12169         MonoGenericParamFull *param;
12170         MonoImage *image;
12171         MonoClass *pklass;
12172         MonoError error;
12173
12174         image = &gparam->tbuilder->module->dynamic_image->image;
12175
12176         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12177
12178         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12179         g_assert (mono_error_ok (&error));
12180         param->param.num = gparam->index;
12181
12182         if (gparam->mbuilder) {
12183                 if (!gparam->mbuilder->generic_container) {
12184                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12185                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12186                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12187                         gparam->mbuilder->generic_container->is_method = TRUE;
12188                         /* 
12189                          * Cannot set owner.method, since the MonoMethod is not created yet.
12190                          * Set the image field instead, so type_in_image () works.
12191                          */
12192                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12193                         gparam->mbuilder->generic_container->owner.image = klass->image;
12194                 }
12195                 param->param.owner = gparam->mbuilder->generic_container;
12196         } else if (gparam->tbuilder) {
12197                 if (!gparam->tbuilder->generic_container) {
12198                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12199                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12200                         gparam->tbuilder->generic_container->owner.klass = klass;
12201                 }
12202                 param->param.owner = gparam->tbuilder->generic_container;
12203         }
12204
12205         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12206
12207         gparam->type.type = &pklass->byval_arg;
12208
12209         mono_class_set_ref_info (pklass, gparam);
12210         mono_image_append_class_to_reflection_info_set (pklass);
12211 }
12212
12213 MonoArray *
12214 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12215 {
12216         MonoError error;
12217         MonoReflectionModuleBuilder *module = sig->module;
12218         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12219         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12220         guint32 buflen, i;
12221         MonoArray *result;
12222         SigBuffer buf;
12223
12224         check_array_for_usertypes (sig->arguments, &error);
12225         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12226
12227         sigbuffer_init (&buf, 32);
12228
12229         sigbuffer_add_value (&buf, 0x07);
12230         sigbuffer_add_value (&buf, na);
12231         if (assembly != NULL){
12232                 for (i = 0; i < na; ++i) {
12233                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12234                         encode_reflection_type (assembly, type, &buf);
12235                 }
12236         }
12237
12238         buflen = buf.p - buf.buf;
12239         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12240         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12241         sigbuffer_free (&buf);
12242
12243         return result;
12244 }
12245
12246 MonoArray *
12247 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12248 {
12249         MonoError error;
12250         MonoDynamicImage *assembly = sig->module->dynamic_image;
12251         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12252         guint32 buflen, i;
12253         MonoArray *result;
12254         SigBuffer buf;
12255
12256         check_array_for_usertypes (sig->arguments, &error);
12257         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12258
12259         sigbuffer_init (&buf, 32);
12260
12261         sigbuffer_add_value (&buf, 0x06);
12262         for (i = 0; i < na; ++i) {
12263                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12264                 encode_reflection_type (assembly, type, &buf);
12265         }
12266
12267         buflen = buf.p - buf.buf;
12268         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12269         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12270         sigbuffer_free (&buf);
12271
12272         return result;
12273 }
12274
12275 typedef struct {
12276         MonoMethod *handle;
12277         MonoDomain *domain;
12278 } DynamicMethodReleaseData;
12279
12280 /*
12281  * The runtime automatically clean up those after finalization.
12282 */      
12283 static MonoReferenceQueue *dynamic_method_queue;
12284
12285 static void
12286 free_dynamic_method (void *dynamic_method)
12287 {
12288         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12289         MonoDomain *domain = data->domain;
12290         MonoMethod *method = data->handle;
12291         guint32 dis_link;
12292
12293         mono_domain_lock (domain);
12294         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12295         g_hash_table_remove (domain->method_to_dyn_method, method);
12296         mono_domain_unlock (domain);
12297         g_assert (dis_link);
12298         mono_gchandle_free (dis_link);
12299
12300         mono_runtime_free_method (domain, method);
12301         g_free (data);
12302 }
12303
12304 void 
12305 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12306 {
12307         MonoReferenceQueue *queue;
12308         MonoMethod *handle;
12309         DynamicMethodReleaseData *release_data;
12310         ReflectionMethodBuilder rmb;
12311         MonoMethodSignature *sig;
12312         MonoClass *klass;
12313         MonoDomain *domain;
12314         GSList *l;
12315         int i;
12316
12317         if (mono_runtime_is_shutting_down ())
12318                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12319
12320         if (!(queue = dynamic_method_queue)) {
12321                 mono_loader_lock ();
12322                 if (!(queue = dynamic_method_queue))
12323                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12324                 mono_loader_unlock ();
12325         }
12326
12327         sig = dynamic_method_to_signature (mb);
12328
12329         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12330
12331         /*
12332          * Resolve references.
12333          */
12334         /* 
12335          * Every second entry in the refs array is reserved for storing handle_class,
12336          * which is needed by the ldtoken implementation in the JIT.
12337          */
12338         rmb.nrefs = mb->nrefs;
12339         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12340         for (i = 0; i < mb->nrefs; i += 2) {
12341                 MonoClass *handle_class;
12342                 gpointer ref;
12343                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12344
12345                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12346                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12347                         /*
12348                          * The referenced DynamicMethod should already be created by the managed
12349                          * code, except in the case of circular references. In that case, we store
12350                          * method in the refs array, and fix it up later when the referenced 
12351                          * DynamicMethod is created.
12352                          */
12353                         if (method->mhandle) {
12354                                 ref = method->mhandle;
12355                         } else {
12356                                 /* FIXME: GC object stored in unmanaged memory */
12357                                 ref = method;
12358
12359                                 /* FIXME: GC object stored in unmanaged memory */
12360                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12361                         }
12362                         handle_class = mono_defaults.methodhandle_class;
12363                 } else {
12364                         MonoException *ex = NULL;
12365                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12366                         if (!ref)
12367                                 ex = mono_get_exception_type_load (NULL, NULL);
12368                         else if (mono_security_core_clr_enabled ())
12369                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12370
12371                         if (ex) {
12372                                 g_free (rmb.refs);
12373                                 mono_raise_exception (ex);
12374                                 return;
12375                         }
12376                 }
12377
12378                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12379                 rmb.refs [i + 1] = handle_class;
12380         }               
12381
12382         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12383
12384         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12385         release_data = g_new (DynamicMethodReleaseData, 1);
12386         release_data->handle = handle;
12387         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12388         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12389                 g_free (release_data);
12390
12391         /* Fix up refs entries pointing at us */
12392         for (l = mb->referenced_by; l; l = l->next) {
12393                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12394                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12395                 gpointer *data;
12396                 
12397                 g_assert (method->mhandle);
12398
12399                 data = (gpointer*)wrapper->method_data;
12400                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12401                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12402                                 data [i + 1] = mb->mhandle;
12403                 }
12404         }
12405         g_slist_free (mb->referenced_by);
12406
12407         g_free (rmb.refs);
12408
12409         /* ilgen is no longer needed */
12410         mb->ilgen = NULL;
12411
12412         domain = mono_domain_get ();
12413         mono_domain_lock (domain);
12414         if (!domain->method_to_dyn_method)
12415                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12416         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12417         mono_domain_unlock (domain);
12418 }
12419
12420 #endif /* DISABLE_REFLECTION_EMIT */
12421
12422 /**
12423  * 
12424  * mono_reflection_is_valid_dynamic_token:
12425  * 
12426  * Returns TRUE if token is valid.
12427  * 
12428  */
12429 gboolean
12430 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12431 {
12432         return lookup_dyn_token (image, token) != NULL;
12433 }
12434
12435 MonoMethodSignature *
12436 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12437 {
12438         MonoMethodSignature *sig;
12439         g_assert (image_is_dynamic (image));
12440
12441         mono_error_init (error);
12442
12443         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12444         if (sig)
12445                 return sig;
12446
12447         return mono_method_signature_checked (method, error);
12448 }
12449
12450 #ifndef DISABLE_REFLECTION_EMIT
12451
12452 /**
12453  * mono_reflection_lookup_dynamic_token:
12454  *
12455  * Finish the Builder object pointed to by TOKEN and return the corresponding
12456  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12457  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12458  * mapping table.
12459  *
12460  * LOCKING: Take the loader lock
12461  */
12462 gpointer
12463 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12464 {
12465         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12466         MonoObject *obj;
12467         MonoClass *klass;
12468
12469         obj = lookup_dyn_token (assembly, token);
12470         if (!obj) {
12471                 if (valid_token)
12472                         g_error ("Could not find required dynamic token 0x%08x", token);
12473                 else
12474                         return NULL;
12475         }
12476
12477         if (!handle_class)
12478                 handle_class = &klass;
12479         return resolve_object (image, obj, handle_class, context);
12480 }
12481
12482 /*
12483  * ensure_complete_type:
12484  *
12485  *   Ensure that KLASS is completed if it is a dynamic type, or references
12486  * dynamic types.
12487  */
12488 static void
12489 ensure_complete_type (MonoClass *klass)
12490 {
12491         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12492                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12493
12494                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12495
12496                 // Asserting here could break a lot of code
12497                 //g_assert (klass->wastypebuilder);
12498         }
12499
12500         if (klass->generic_class) {
12501                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12502                 int i;
12503
12504                 for (i = 0; i < inst->type_argc; ++i) {
12505                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12506                 }
12507         }
12508 }
12509
12510 static gpointer
12511 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12512 {
12513         gpointer result = NULL;
12514
12515         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12516                 result = mono_string_intern ((MonoString*)obj);
12517                 *handle_class = mono_defaults.string_class;
12518                 g_assert (result);
12519         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12520                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12521                 MonoClass *mc = mono_class_from_mono_type (type);
12522                 if (!mono_class_init (mc))
12523                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12524
12525                 if (context) {
12526                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12527                         result = mono_class_from_mono_type (inflated);
12528                         mono_metadata_free_type (inflated);
12529                 } else {
12530                         result = mono_class_from_mono_type (type);
12531                 }
12532                 *handle_class = mono_defaults.typehandle_class;
12533                 g_assert (result);
12534         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12535                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12536                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12537                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12538                 result = ((MonoReflectionMethod*)obj)->method;
12539                 if (context) {
12540                         MonoError error;
12541                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12542                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12543                 }
12544                 *handle_class = mono_defaults.methodhandle_class;
12545                 g_assert (result);
12546         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12547                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12548                 result = mb->mhandle;
12549                 if (!result) {
12550                         /* Type is not yet created */
12551                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12552
12553                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12554
12555                         /*
12556                          * Hopefully this has been filled in by calling CreateType() on the
12557                          * TypeBuilder.
12558                          */
12559                         /*
12560                          * TODO: This won't work if the application finishes another 
12561                          * TypeBuilder instance instead of this one.
12562                          */
12563                         result = mb->mhandle;
12564                 }
12565                 if (context) {
12566                         MonoError error;
12567                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12568                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12569                 }
12570                 *handle_class = mono_defaults.methodhandle_class;
12571         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12572                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12573
12574                 result = cb->mhandle;
12575                 if (!result) {
12576                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12577
12578                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12579                         result = cb->mhandle;
12580                 }
12581                 if (context) {
12582                         MonoError error;
12583                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12584                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12585                 }
12586                 *handle_class = mono_defaults.methodhandle_class;
12587         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12588                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12589
12590                 ensure_complete_type (field->parent);
12591                 if (context) {
12592                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12593                         MonoClass *klass = mono_class_from_mono_type (inflated);
12594                         MonoClassField *inflated_field;
12595                         gpointer iter = NULL;
12596                         mono_metadata_free_type (inflated);
12597                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12598                                 if (!strcmp (field->name, inflated_field->name))
12599                                         break;
12600                         }
12601                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12602                         result = inflated_field;
12603                 } else {
12604                         result = field;
12605                 }
12606                 *handle_class = mono_defaults.fieldhandle_class;
12607                 g_assert (result);
12608         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12609                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12610                 result = fb->handle;
12611
12612                 if (!result) {
12613                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12614
12615                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12616                         result = fb->handle;
12617                 }
12618
12619                 if (fb->handle && fb->handle->parent->generic_container) {
12620                         MonoClass *klass = fb->handle->parent;
12621                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12622                         MonoClass *inflated = mono_class_from_mono_type (type);
12623
12624                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12625                         g_assert (result);
12626                         mono_metadata_free_type (type);
12627                 }
12628                 *handle_class = mono_defaults.fieldhandle_class;
12629         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12630                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12631                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12632                 MonoClass *klass;
12633
12634                 klass = type->data.klass;
12635                 if (klass->wastypebuilder) {
12636                         /* Already created */
12637                         result = klass;
12638                 }
12639                 else {
12640                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12641                         result = type->data.klass;
12642                         g_assert (result);
12643                 }
12644                 *handle_class = mono_defaults.typehandle_class;
12645         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12646                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12647                 MonoMethodSignature *sig;
12648                 int nargs, i;
12649
12650                 if (helper->arguments)
12651                         nargs = mono_array_length (helper->arguments);
12652                 else
12653                         nargs = 0;
12654
12655                 sig = mono_metadata_signature_alloc (image, nargs);
12656                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12657                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12658
12659                 if (helper->unmanaged_call_conv) { /* unmanaged */
12660                         sig->call_convention = helper->unmanaged_call_conv - 1;
12661                         sig->pinvoke = TRUE;
12662                 } else if (helper->call_conv & 0x02) {
12663                         sig->call_convention = MONO_CALL_VARARG;
12664                 } else {
12665                         sig->call_convention = MONO_CALL_DEFAULT;
12666                 }
12667
12668                 sig->param_count = nargs;
12669                 /* TODO: Copy type ? */
12670                 sig->ret = helper->return_type->type;
12671                 for (i = 0; i < nargs; ++i)
12672                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12673
12674                 result = sig;
12675                 *handle_class = NULL;
12676         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12677                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12678                 /* Already created by the managed code */
12679                 g_assert (method->mhandle);
12680                 result = method->mhandle;
12681                 *handle_class = mono_defaults.methodhandle_class;
12682         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12683                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12684                 type = mono_class_inflate_generic_type (type, context);
12685                 result = mono_class_from_mono_type (type);
12686                 *handle_class = mono_defaults.typehandle_class;
12687                 g_assert (result);
12688                 mono_metadata_free_type (type);
12689         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12690                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12691                 type = mono_class_inflate_generic_type (type, context);
12692                 result = mono_class_from_mono_type (type);
12693                 *handle_class = mono_defaults.typehandle_class;
12694                 g_assert (result);
12695                 mono_metadata_free_type (type);
12696         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12697                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12698                 MonoClass *inflated;
12699                 MonoType *type;
12700                 MonoClassField *field;
12701
12702                 if (is_sre_field_builder (mono_object_class (f->fb)))
12703                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12704                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12705                         field = ((MonoReflectionField*)f->fb)->field;
12706                 else
12707                         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)));
12708
12709                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12710                 inflated = mono_class_from_mono_type (type);
12711
12712                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12713                 ensure_complete_type (field->parent);
12714                 g_assert (result);
12715                 mono_metadata_free_type (type);
12716                 *handle_class = mono_defaults.fieldhandle_class;
12717         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12718                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12719                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12720                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12721                 MonoMethod *method;
12722
12723                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12724                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12725                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12726                         method = ((MonoReflectionMethod *)c->cb)->method;
12727                 else
12728                         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)));
12729
12730                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12731                 *handle_class = mono_defaults.methodhandle_class;
12732                 mono_metadata_free_type (type);
12733         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12734                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12735                 if (m->method_args) {
12736                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12737                         if (context) {
12738                                 MonoError error;
12739                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12740                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12741                         }
12742                 } else {
12743                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12744                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12745                         MonoMethod *method;
12746
12747                         if (is_sre_method_builder (mono_object_class (m->mb)))
12748                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12749                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12750                                 method = ((MonoReflectionMethod *)m->mb)->method;
12751                         else
12752                                 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)));
12753
12754                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12755                         mono_metadata_free_type (type);
12756                 }
12757                 *handle_class = mono_defaults.methodhandle_class;
12758         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12759                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12760                 MonoType *mtype;
12761                 MonoClass *klass;
12762                 MonoMethod *method;
12763                 gpointer iter;
12764                 char *name;
12765
12766                 mtype = mono_reflection_type_get_handle (m->parent);
12767                 klass = mono_class_from_mono_type (mtype);
12768
12769                 /* Find the method */
12770
12771                 name = mono_string_to_utf8 (m->name);
12772                 iter = NULL;
12773                 while ((method = mono_class_get_methods (klass, &iter))) {
12774                         if (!strcmp (method->name, name))
12775                                 break;
12776                 }
12777                 g_free (name);
12778
12779                 // FIXME:
12780                 g_assert (method);
12781                 // FIXME: Check parameters/return value etc. match
12782
12783                 result = method;
12784                 *handle_class = mono_defaults.methodhandle_class;
12785         } else if (is_sre_array (mono_object_get_class(obj)) ||
12786                                 is_sre_byref (mono_object_get_class(obj)) ||
12787                                 is_sre_pointer (mono_object_get_class(obj))) {
12788                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12789                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12790
12791                 if (context) {
12792                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12793                         result = mono_class_from_mono_type (inflated);
12794                         mono_metadata_free_type (inflated);
12795                 } else {
12796                         result = mono_class_from_mono_type (type);
12797                 }
12798                 *handle_class = mono_defaults.typehandle_class;
12799         } else {
12800                 g_print ("%s\n", obj->vtable->klass->name);
12801                 g_assert_not_reached ();
12802         }
12803         return result;
12804 }
12805
12806 #else /* DISABLE_REFLECTION_EMIT */
12807
12808 MonoArray*
12809 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12810 {
12811         g_assert_not_reached ();
12812         return NULL;
12813 }
12814
12815 void
12816 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12817 {
12818         g_assert_not_reached ();
12819 }
12820
12821 void
12822 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12823 {
12824         g_assert_not_reached ();
12825 }
12826
12827 void
12828 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12829 {
12830         g_assert_not_reached ();
12831 }
12832
12833 void
12834 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12835 {
12836         g_assert_not_reached ();
12837 }
12838
12839 void
12840 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12841 {
12842         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12843 }
12844
12845 void
12846 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12847 {
12848         g_assert_not_reached ();
12849 }
12850
12851 void
12852 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12853 {
12854         g_assert_not_reached ();
12855 }
12856
12857 MonoReflectionModule *
12858 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12859 {
12860         g_assert_not_reached ();
12861         return NULL;
12862 }
12863
12864 guint32
12865 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12866 {
12867         g_assert_not_reached ();
12868         return 0;
12869 }
12870
12871 guint32
12872 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12873 {
12874         g_assert_not_reached ();
12875         return 0;
12876 }
12877
12878 guint32
12879 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12880                                                  gboolean create_open_instance, gboolean register_token)
12881 {
12882         g_assert_not_reached ();
12883         return 0;
12884 }
12885
12886 void
12887 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12888 {
12889 }
12890
12891 void
12892 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12893 {
12894         g_assert_not_reached ();
12895 }
12896
12897 void
12898 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12899 {
12900         *overrides = NULL;
12901         *num_overrides = 0;
12902 }
12903
12904 MonoReflectionEvent *
12905 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12906 {
12907         g_assert_not_reached ();
12908         return NULL;
12909 }
12910
12911 MonoReflectionType*
12912 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12913 {
12914         g_assert_not_reached ();
12915         return NULL;
12916 }
12917
12918 void
12919 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12920 {
12921         g_assert_not_reached ();
12922 }
12923
12924 MonoArray *
12925 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12926 {
12927         g_assert_not_reached ();
12928         return NULL;
12929 }
12930
12931 MonoArray *
12932 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12933 {
12934         g_assert_not_reached ();
12935         return NULL;
12936 }
12937
12938 void 
12939 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12940 {
12941 }
12942
12943 gpointer
12944 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12945 {
12946         return NULL;
12947 }
12948
12949 MonoType*
12950 mono_reflection_type_get_handle (MonoReflectionType* ref)
12951 {
12952         if (!ref)
12953                 return NULL;
12954         return ref->type;
12955 }
12956
12957 void
12958 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12959 {
12960         g_assert_not_reached ();
12961 }
12962
12963 #endif /* DISABLE_REFLECTION_EMIT */
12964
12965 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12966 const static guint32 declsec_flags_map[] = {
12967         0x00000000,                                     /* empty */
12968         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12969         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12970         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12971         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12972         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12973         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12974         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12975         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12976         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12977         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12978         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12979         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12980         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12981         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12982         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12983         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12984         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12985         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12986 };
12987
12988 /*
12989  * Returns flags that includes all available security action associated to the handle.
12990  * @token: metadata token (either for a class or a method)
12991  * @image: image where resides the metadata.
12992  */
12993 static guint32
12994 mono_declsec_get_flags (MonoImage *image, guint32 token)
12995 {
12996         int index = mono_metadata_declsec_from_index (image, token);
12997         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12998         guint32 result = 0;
12999         guint32 action;
13000         int i;
13001
13002         /* HasSecurity can be present for other, not specially encoded, attributes,
13003            e.g. SuppressUnmanagedCodeSecurityAttribute */
13004         if (index < 0)
13005                 return 0;
13006
13007         for (i = index; i < t->rows; i++) {
13008                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13009
13010                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13011                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13012                         break;
13013
13014                 action = cols [MONO_DECL_SECURITY_ACTION];
13015                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13016                         result |= declsec_flags_map [action];
13017                 } else {
13018                         g_assert_not_reached ();
13019                 }
13020         }
13021         return result;
13022 }
13023
13024 /*
13025  * Get the security actions (in the form of flags) associated with the specified method.
13026  *
13027  * @method: The method for which we want the declarative security flags.
13028  * Return the declarative security flags for the method (only).
13029  *
13030  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13031  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13032  */
13033 guint32
13034 mono_declsec_flags_from_method (MonoMethod *method)
13035 {
13036         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13037                 /* FIXME: No cache (for the moment) */
13038                 guint32 idx = mono_method_get_index (method);
13039                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13040                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13041                 return mono_declsec_get_flags (method->klass->image, idx);
13042         }
13043         return 0;
13044 }
13045
13046 /*
13047  * Get the security actions (in the form of flags) associated with the specified class.
13048  *
13049  * @klass: The class for which we want the declarative security flags.
13050  * Return the declarative security flags for the class.
13051  *
13052  * Note: We cache the flags inside the MonoClass structure as this will get 
13053  *       called very often (at least for each method).
13054  */
13055 guint32
13056 mono_declsec_flags_from_class (MonoClass *klass)
13057 {
13058         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13059                 if (!klass->ext || !klass->ext->declsec_flags) {
13060                         guint32 idx;
13061
13062                         idx = mono_metadata_token_index (klass->type_token);
13063                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13064                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13065                         mono_loader_lock ();
13066                         mono_class_alloc_ext (klass);
13067                         mono_loader_unlock ();
13068                         /* we cache the flags on classes */
13069                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13070                 }
13071                 return klass->ext->declsec_flags;
13072         }
13073         return 0;
13074 }
13075
13076 /*
13077  * Get the security actions (in the form of flags) associated with the specified assembly.
13078  *
13079  * @assembly: The assembly for which we want the declarative security flags.
13080  * Return the declarative security flags for the assembly.
13081  */
13082 guint32
13083 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13084 {
13085         guint32 idx = 1; /* there is only one assembly */
13086         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13087         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13088         return mono_declsec_get_flags (assembly->image, idx);
13089 }
13090
13091
13092 /*
13093  * Fill actions for the specific index (which may either be an encoded class token or
13094  * an encoded method token) from the metadata image.
13095  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13096  */
13097 static MonoBoolean
13098 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13099         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13100 {
13101         MonoBoolean result = FALSE;
13102         MonoTableInfo *t;
13103         guint32 cols [MONO_DECL_SECURITY_SIZE];
13104         int index = mono_metadata_declsec_from_index (image, token);
13105         int i;
13106
13107         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13108         for (i = index; i < t->rows; i++) {
13109                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13110
13111                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13112                         return result;
13113
13114                 /* if present only replace (class) permissions with method permissions */
13115                 /* if empty accept either class or method permissions */
13116                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13117                         if (!actions->demand.blob) {
13118                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13119                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13120                                 actions->demand.blob = (char*) (blob + 2);
13121                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13122                                 result = TRUE;
13123                         }
13124                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13125                         if (!actions->noncasdemand.blob) {
13126                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13127                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13128                                 actions->noncasdemand.blob = (char*) (blob + 2);
13129                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13130                                 result = TRUE;
13131                         }
13132                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13133                         if (!actions->demandchoice.blob) {
13134                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13135                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13136                                 actions->demandchoice.blob = (char*) (blob + 2);
13137                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13138                                 result = TRUE;
13139                         }
13140                 }
13141         }
13142
13143         return result;
13144 }
13145
13146 static MonoBoolean
13147 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13148         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13149 {
13150         guint32 idx = mono_metadata_token_index (klass->type_token);
13151         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13152         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13153         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13154 }
13155
13156 static MonoBoolean
13157 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13158         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13159 {
13160         guint32 idx = mono_method_get_index (method);
13161         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13162         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13163         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13164 }
13165
13166 /*
13167  * Collect all actions (that requires to generate code in mini) assigned for
13168  * the specified method.
13169  * Note: Don't use the content of actions if the function return FALSE.
13170  */
13171 MonoBoolean
13172 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13173 {
13174         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13175                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13176         MonoBoolean result = FALSE;
13177         guint32 flags;
13178
13179         /* quick exit if no declarative security is present in the metadata */
13180         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13181                 return FALSE;
13182
13183         /* we want the original as the wrapper is "free" of the security informations */
13184         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13185                 method = mono_marshal_method_from_wrapper (method);
13186                 if (!method)
13187                         return FALSE;
13188         }
13189
13190         /* First we look for method-level attributes */
13191         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13192                 mono_class_init (method->klass);
13193                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13194
13195                 result = mono_declsec_get_method_demands_params (method, demands, 
13196                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13197         }
13198
13199         /* Here we use (or create) the class declarative cache to look for demands */
13200         flags = mono_declsec_flags_from_class (method->klass);
13201         if (flags & mask) {
13202                 if (!result) {
13203                         mono_class_init (method->klass);
13204                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13205                 }
13206                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13207                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13208         }
13209
13210         /* The boolean return value is used as a shortcut in case nothing needs to
13211            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13212         return result;
13213 }
13214
13215
13216 /*
13217  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13218  *
13219  * Note: Don't use the content of actions if the function return FALSE.
13220  */
13221 MonoBoolean
13222 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13223 {
13224         MonoBoolean result = FALSE;
13225         guint32 flags;
13226
13227         /* quick exit if no declarative security is present in the metadata */
13228         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13229                 return FALSE;
13230
13231         /* we want the original as the wrapper is "free" of the security informations */
13232         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13233                 method = mono_marshal_method_from_wrapper (method);
13234                 if (!method)
13235                         return FALSE;
13236         }
13237
13238         /* results are independant - zeroize both */
13239         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13240         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13241
13242         /* First we look for method-level attributes */
13243         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13244                 mono_class_init (method->klass);
13245
13246                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13247                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13248         }
13249
13250         /* Here we use (or create) the class declarative cache to look for demands */
13251         flags = mono_declsec_flags_from_class (method->klass);
13252         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13253                 mono_class_init (method->klass);
13254
13255                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13256                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13257         }
13258
13259         return result;
13260 }
13261
13262 /*
13263  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13264  *
13265  * @klass       The inherited class - this is the class that provides the security check (attributes)
13266  * @demans      
13267  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13268  * 
13269  * Note: Don't use the content of actions if the function return FALSE.
13270  */
13271 MonoBoolean
13272 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13273 {
13274         MonoBoolean result = FALSE;
13275         guint32 flags;
13276
13277         /* quick exit if no declarative security is present in the metadata */
13278         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13279                 return FALSE;
13280
13281         /* Here we use (or create) the class declarative cache to look for demands */
13282         flags = mono_declsec_flags_from_class (klass);
13283         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13284                 mono_class_init (klass);
13285                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13286
13287                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13288                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13289         }
13290
13291         return result;
13292 }
13293
13294 /*
13295  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13296  *
13297  * Note: Don't use the content of actions if the function return FALSE.
13298  */
13299 MonoBoolean
13300 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13301 {
13302         /* quick exit if no declarative security is present in the metadata */
13303         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13304                 return FALSE;
13305
13306         /* we want the original as the wrapper is "free" of the security informations */
13307         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13308                 method = mono_marshal_method_from_wrapper (method);
13309                 if (!method)
13310                         return FALSE;
13311         }
13312
13313         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13314                 mono_class_init (method->klass);
13315                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13316
13317                 return mono_declsec_get_method_demands_params (method, demands, 
13318                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13319         }
13320         return FALSE;
13321 }
13322
13323
13324 static MonoBoolean
13325 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13326 {
13327         guint32 cols [MONO_DECL_SECURITY_SIZE];
13328         MonoTableInfo *t;
13329         int i;
13330
13331         int index = mono_metadata_declsec_from_index (image, token);
13332         if (index == -1)
13333                 return FALSE;
13334
13335         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13336         for (i = index; i < t->rows; i++) {
13337                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13338
13339                 /* shortcut - index are ordered */
13340                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13341                         return FALSE;
13342
13343                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13344                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13345                         entry->blob = (char*) (metadata + 2);
13346                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13347                         return TRUE;
13348                 }
13349         }
13350
13351         return FALSE;
13352 }
13353
13354 MonoBoolean
13355 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13356 {
13357         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13358                 guint32 idx = mono_method_get_index (method);
13359                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13360                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13361                 return get_declsec_action (method->klass->image, idx, action, entry);
13362         }
13363         return FALSE;
13364 }
13365
13366 MonoBoolean
13367 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13368 {
13369         /* use cache */
13370         guint32 flags = mono_declsec_flags_from_class (klass);
13371         if (declsec_flags_map [action] & flags) {
13372                 guint32 idx = mono_metadata_token_index (klass->type_token);
13373                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13374                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13375                 return get_declsec_action (klass->image, idx, action, entry);
13376         }
13377         return FALSE;
13378 }
13379
13380 MonoBoolean
13381 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13382 {
13383         guint32 idx = 1; /* there is only one assembly */
13384         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13385         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13386
13387         return get_declsec_action (assembly->image, idx, action, entry);
13388 }
13389
13390 gboolean
13391 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13392 {
13393         MonoError error;
13394         MonoObject *res, *exc;
13395         void *params [1];
13396         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13397         static MonoMethod *method = NULL;
13398
13399         if (!System_Reflection_Emit_TypeBuilder) {
13400                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13401                 g_assert (System_Reflection_Emit_TypeBuilder);
13402         }
13403         if (method == NULL) {
13404                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13405                 g_assert (method);
13406         }
13407
13408         /* 
13409          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13410          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13411          */
13412         g_assert (mono_class_get_ref_info (klass));
13413         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13414
13415         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13416         mono_error_raise_exception (&error); /* FIXME don't raise here */
13417
13418         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13419         if (exc)
13420                 return FALSE;
13421         else
13422                 return *(MonoBoolean*)mono_object_unbox (res);
13423 }
13424
13425 /**
13426  * mono_reflection_type_get_type:
13427  * @reftype: the System.Type object
13428  *
13429  * Returns the MonoType* associated with the C# System.Type object @reftype.
13430  */
13431 MonoType*
13432 mono_reflection_type_get_type (MonoReflectionType *reftype)
13433 {
13434         g_assert (reftype);
13435
13436         return mono_reflection_type_get_handle (reftype);
13437 }
13438
13439 /**
13440  * mono_reflection_assembly_get_assembly:
13441  * @refassembly: the System.Reflection.Assembly object
13442  *
13443  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13444  */
13445 MonoAssembly*
13446 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13447 {
13448         g_assert (refassembly);
13449
13450         return refassembly->assembly;
13451 }
13452