[reflection] Don't raise in reflection_methodbuilder_from_{method,ctor}_builder
[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 gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
224
225 static inline void
226 dynamic_images_lock (void)
227 {
228         mono_os_mutex_lock (&dynamic_images_mutex);
229 }
230
231 static inline void
232 dynamic_images_unlock (void)
233 {
234         mono_os_mutex_unlock (&dynamic_images_mutex);
235 }
236
237 /**
238  * mono_find_dynamic_image_owner:
239  *
240  * Find the dynamic image, if any, which a given pointer is located in the memory of.
241  */
242 MonoImage *
243 mono_find_dynamic_image_owner (void *ptr)
244 {
245         MonoImage *owner = NULL;
246         int i;
247
248         dynamic_images_lock ();
249
250         if (dynamic_images)
251         {
252                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254                         if (mono_mempool_contains_addr (image->mempool, ptr))
255                                 owner = image;
256                 }
257         }
258
259         dynamic_images_unlock ();
260
261         return owner;
262 }
263
264 void
265 mono_reflection_init (void)
266 {
267         mono_os_mutex_init (&dynamic_images_mutex);
268 }
269
270 static inline void
271 dynamic_image_lock (MonoDynamicImage *image)
272 {
273         MONO_PREPARE_BLOCKING;
274         mono_image_lock ((MonoImage*)image);
275         MONO_FINISH_BLOCKING;
276 }
277
278 static inline void
279 dynamic_image_unlock (MonoDynamicImage *image)
280 {
281         mono_image_unlock ((MonoImage*)image);
282 }
283
284 static void
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
286 {
287         MONO_REQ_GC_UNSAFE_MODE;
288
289         dynamic_image_lock (assembly);
290         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291         dynamic_image_unlock (assembly);
292 }
293
294 static MonoObject*
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
296 {
297         MONO_REQ_GC_UNSAFE_MODE;
298
299         MonoObject *obj;
300
301         dynamic_image_lock (assembly);
302         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303         dynamic_image_unlock (assembly);
304
305         return obj;
306 }
307
308 static void
309 sigbuffer_init (SigBuffer *buf, int size)
310 {
311         MONO_REQ_GC_NEUTRAL_MODE;
312
313         buf->buf = (char *)g_malloc (size);
314         buf->p = buf->buf;
315         buf->end = buf->buf + size;
316 }
317
318 static void
319 sigbuffer_make_room (SigBuffer *buf, int size)
320 {
321         MONO_REQ_GC_NEUTRAL_MODE;
322
323         if (buf->end - buf->p < size) {
324                 int new_size = buf->end - buf->buf + size + 32;
325                 char *p = (char *)g_realloc (buf->buf, new_size);
326                 size = buf->p - buf->buf;
327                 buf->buf = p;
328                 buf->p = p + size;
329                 buf->end = buf->buf + new_size;
330         }
331 }
332
333 static void
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
335 {
336         MONO_REQ_GC_NEUTRAL_MODE;
337
338         sigbuffer_make_room (buf, 6);
339         mono_metadata_encode_value (val, buf->p, &buf->p);
340 }
341
342 static void
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
344 {
345         MONO_REQ_GC_NEUTRAL_MODE;
346
347         sigbuffer_make_room (buf, 1);
348         buf->p [0] = val;
349         buf->p++;
350 }
351
352 static void
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
354 {
355         MONO_REQ_GC_NEUTRAL_MODE;
356
357         sigbuffer_make_room (buf, size);
358         memcpy (buf->p, p, size);
359         buf->p += size;
360 }
361
362 static void
363 sigbuffer_free (SigBuffer *buf)
364 {
365         MONO_REQ_GC_NEUTRAL_MODE;
366
367         g_free (buf->buf);
368 }
369
370 #ifndef DISABLE_REFLECTION_EMIT
371 /**
372  * mp_g_alloc:
373  *
374  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
375  * from the C heap.
376  */
377 static gpointer
378 image_g_malloc (MonoImage *image, guint size)
379 {
380         MONO_REQ_GC_NEUTRAL_MODE;
381
382         if (image)
383                 return mono_image_alloc (image, size);
384         else
385                 return g_malloc (size);
386 }
387 #endif /* !DISABLE_REFLECTION_EMIT */
388
389 /**
390  * image_g_alloc0:
391  *
392  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
393  * from the C heap.
394  */
395 static gpointer
396 image_g_malloc0 (MonoImage *image, guint size)
397 {
398         MONO_REQ_GC_NEUTRAL_MODE;
399
400         if (image)
401                 return mono_image_alloc0 (image, size);
402         else
403                 return g_malloc0 (size);
404 }
405
406 #ifndef DISABLE_REFLECTION_EMIT
407 static char*
408 image_strdup (MonoImage *image, const char *s)
409 {
410         MONO_REQ_GC_NEUTRAL_MODE;
411
412         if (image)
413                 return mono_image_strdup (image, s);
414         else
415                 return g_strdup (s);
416 }
417 #endif
418
419 #define image_g_new(image,struct_type, n_structs)               \
420     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
421
422 #define image_g_new0(image,struct_type, n_structs)              \
423     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
424
425
426 static void
427 alloc_table (MonoDynamicTable *table, guint nrows)
428 {
429         MONO_REQ_GC_NEUTRAL_MODE;
430
431         table->rows = nrows;
432         g_assert (table->columns);
433         if (nrows + 1 >= table->alloc_rows) {
434                 while (nrows + 1 >= table->alloc_rows) {
435                         if (table->alloc_rows == 0)
436                                 table->alloc_rows = 16;
437                         else
438                                 table->alloc_rows *= 2;
439                 }
440
441                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
442         }
443 }
444
445 static void
446 make_room_in_stream (MonoDynamicStream *stream, int size)
447 {
448         MONO_REQ_GC_NEUTRAL_MODE;
449
450         if (size <= stream->alloc_size)
451                 return;
452         
453         while (stream->alloc_size <= size) {
454                 if (stream->alloc_size < 4096)
455                         stream->alloc_size = 4096;
456                 else
457                         stream->alloc_size *= 2;
458         }
459         
460         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
461 }
462
463 static guint32
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
465 {
466         MONO_REQ_GC_NEUTRAL_MODE;
467
468         guint32 idx;
469         guint32 len;
470         gpointer oldkey, oldval;
471
472         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473                 return GPOINTER_TO_UINT (oldval);
474
475         len = strlen (str) + 1;
476         idx = sh->index;
477         
478         make_room_in_stream (sh, idx + len);
479
480         /*
481          * We strdup the string even if we already copy them in sh->data
482          * so that the string pointers in the hash remain valid even if
483          * we need to realloc sh->data. We may want to avoid that later.
484          */
485         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486         memcpy (sh->data + idx, str, len);
487         sh->index += len;
488         return idx;
489 }
490
491 static guint32
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
493 {
494         MONO_REQ_GC_UNSAFE_MODE;
495
496         char *name = mono_string_to_utf8 (str);
497         guint32 idx;
498         idx = string_heap_insert (sh, name);
499         g_free (name);
500         return idx;
501 }
502
503 #ifndef DISABLE_REFLECTION_EMIT
504 static void
505 string_heap_init (MonoDynamicStream *sh)
506 {
507         MONO_REQ_GC_NEUTRAL_MODE;
508
509         sh->index = 0;
510         sh->alloc_size = 4096;
511         sh->data = (char *)g_malloc (4096);
512         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513         string_heap_insert (sh, "");
514 }
515 #endif
516
517 static guint32
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
519 {
520         MONO_REQ_GC_NEUTRAL_MODE;
521
522         guint32 idx;
523         
524         make_room_in_stream (stream, stream->index + len);
525         memcpy (stream->data + stream->index, data, len);
526         idx = stream->index;
527         stream->index += len;
528         /* 
529          * align index? Not without adding an additional param that controls it since
530          * we may store a blob value in pieces.
531          */
532         return idx;
533 }
534
535 static guint32
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
537 {
538         MONO_REQ_GC_NEUTRAL_MODE;
539
540         guint32 idx;
541         
542         make_room_in_stream (stream, stream->index + len);
543         memset (stream->data + stream->index, 0, len);
544         idx = stream->index;
545         stream->index += len;
546         return idx;
547 }
548
549 static void
550 stream_data_align (MonoDynamicStream *stream)
551 {
552         MONO_REQ_GC_NEUTRAL_MODE;
553
554         char buf [4] = {0};
555         guint32 count = stream->index % 4;
556
557         /* we assume the stream data will be aligned */
558         if (count)
559                 mono_image_add_stream_data (stream, buf, 4 - count);
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static int
564 mono_blob_entry_hash (const char* str)
565 {
566         MONO_REQ_GC_NEUTRAL_MODE;
567
568         guint len, h;
569         const char *end;
570         len = mono_metadata_decode_blob_size (str, &str);
571         if (len > 0) {
572                 end = str + len;
573                 h = *str;
574                 for (str += 1; str < end; str++)
575                         h = (h << 5) - h + *str;
576                 return h;
577         } else {
578                 return 0;
579         }
580 }
581
582 static gboolean
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584         MONO_REQ_GC_NEUTRAL_MODE;
585
586         int len, len2;
587         const char *end1;
588         const char *end2;
589         len = mono_metadata_decode_blob_size (str1, &end1);
590         len2 = mono_metadata_decode_blob_size (str2, &end2);
591         if (len != len2)
592                 return 0;
593         return memcmp (end1, end2, len) == 0;
594 }
595 #endif
596 static guint32
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
598 {
599         MONO_REQ_GC_NEUTRAL_MODE;
600
601         guint32 idx;
602         char *copy;
603         gpointer oldkey, oldval;
604
605         copy = (char *)g_malloc (s1+s2);
606         memcpy (copy, b1, s1);
607         memcpy (copy + s1, b2, s2);
608         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
609                 g_free (copy);
610                 idx = GPOINTER_TO_UINT (oldval);
611         } else {
612                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613                 mono_image_add_stream_data (&assembly->blob, b2, s2);
614                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
615         }
616         return idx;
617 }
618
619 static guint32
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
621 {
622         MONO_REQ_GC_NEUTRAL_MODE;
623
624         char blob_size [8];
625         char *b = blob_size;
626         guint32 size = buf->p - buf->buf;
627         /* store length */
628         g_assert (size <= (buf->end - buf->buf));
629         mono_metadata_encode_value (size, b, &b);
630         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
631 }
632
633 /*
634  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635  * dest may be misaligned.
636  */
637 static void
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639         MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
641         int elem;
642
643         for (elem = 0; elem < nelem; ++elem) {
644                 switch (len) {
645                 case 1:
646                         *dest = *val;
647                         break;
648                 case 2:
649                         dest [0] = val [1];
650                         dest [1] = val [0];
651                         break;
652                 case 4:
653                         dest [0] = val [3];
654                         dest [1] = val [2];
655                         dest [2] = val [1];
656                         dest [3] = val [0];
657                         break;
658                 case 8:
659                         dest [0] = val [7];
660                         dest [1] = val [6];
661                         dest [2] = val [5];
662                         dest [3] = val [4];
663                         dest [4] = val [3];
664                         dest [5] = val [2];
665                         dest [6] = val [1];
666                         dest [7] = val [0];
667                         break;
668                 default:
669                         g_assert_not_reached ();
670                 }
671                 dest += len;
672                 val += len;
673         }
674 #else
675         memcpy (dest, val, len * nelem);
676 #endif
677 }
678
679 static guint32
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
681 {
682         MONO_REQ_GC_UNSAFE_MODE;
683         
684         char blob_size [64];
685         char *b = blob_size;
686         guint32 idx = 0, len;
687
688         len = str->length * 2;
689         mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
691         {
692                 char *swapped = g_malloc (2 * mono_string_length (str));
693                 const char *p = (const char*)mono_string_chars (str);
694
695                 swap_with_size (swapped, p, 2, mono_string_length (str));
696                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
697                 g_free (swapped);
698         }
699 #else
700         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
701 #endif
702         return idx;
703 }
704
705 #ifndef DISABLE_REFLECTION_EMIT
706 static MonoClass *
707 default_class_from_mono_type (MonoType *type)
708 {
709         MONO_REQ_GC_NEUTRAL_MODE;
710
711         switch (type->type) {
712         case MONO_TYPE_OBJECT:
713                 return mono_defaults.object_class;
714         case MONO_TYPE_VOID:
715                 return mono_defaults.void_class;
716         case MONO_TYPE_BOOLEAN:
717                 return mono_defaults.boolean_class;
718         case MONO_TYPE_CHAR:
719                 return mono_defaults.char_class;
720         case MONO_TYPE_I1:
721                 return mono_defaults.sbyte_class;
722         case MONO_TYPE_U1:
723                 return mono_defaults.byte_class;
724         case MONO_TYPE_I2:
725                 return mono_defaults.int16_class;
726         case MONO_TYPE_U2:
727                 return mono_defaults.uint16_class;
728         case MONO_TYPE_I4:
729                 return mono_defaults.int32_class;
730         case MONO_TYPE_U4:
731                 return mono_defaults.uint32_class;
732         case MONO_TYPE_I:
733                 return mono_defaults.int_class;
734         case MONO_TYPE_U:
735                 return mono_defaults.uint_class;
736         case MONO_TYPE_I8:
737                 return mono_defaults.int64_class;
738         case MONO_TYPE_U8:
739                 return mono_defaults.uint64_class;
740         case MONO_TYPE_R4:
741                 return mono_defaults.single_class;
742         case MONO_TYPE_R8:
743                 return mono_defaults.double_class;
744         case MONO_TYPE_STRING:
745                 return mono_defaults.string_class;
746         default:
747                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748                 g_assert_not_reached ();
749         }
750         
751         return NULL;
752 }
753 #endif
754
755 /*
756  * mono_class_get_ref_info:
757  *
758  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
759  */
760 gpointer
761 mono_class_get_ref_info (MonoClass *klass)
762 {
763         MONO_REQ_GC_UNSAFE_MODE;
764
765         if (klass->ref_info_handle == 0)
766                 return NULL;
767         else
768                 return mono_gchandle_get_target (klass->ref_info_handle);
769 }
770
771 void
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
773 {
774         MONO_REQ_GC_UNSAFE_MODE;
775
776         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777         g_assert (klass->ref_info_handle != 0);
778 }
779
780 void
781 mono_class_free_ref_info (MonoClass *klass)
782 {
783         MONO_REQ_GC_NEUTRAL_MODE;
784
785         if (klass->ref_info_handle) {
786                 mono_gchandle_free (klass->ref_info_handle);
787                 klass->ref_info_handle = 0;
788         }
789 }
790
791 static void
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
793 {
794         MONO_REQ_GC_NEUTRAL_MODE;
795
796         int i;
797         MonoGenericInst *class_inst;
798         MonoClass *klass;
799
800         g_assert (gclass);
801
802         class_inst = gclass->context.class_inst;
803
804         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805         klass = gclass->container_class;
806         sigbuffer_add_value (buf, klass->byval_arg.type);
807         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
808
809         sigbuffer_add_value (buf, class_inst->type_argc);
810         for (i = 0; i < class_inst->type_argc; ++i)
811                 encode_type (assembly, class_inst->type_argv [i], buf);
812
813 }
814
815 static void
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (!type) {
821                 g_assert_not_reached ();
822                 return;
823         }
824                 
825         if (type->byref)
826                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
827
828         switch (type->type){
829         case MONO_TYPE_VOID:
830         case MONO_TYPE_BOOLEAN:
831         case MONO_TYPE_CHAR:
832         case MONO_TYPE_I1:
833         case MONO_TYPE_U1:
834         case MONO_TYPE_I2:
835         case MONO_TYPE_U2:
836         case MONO_TYPE_I4:
837         case MONO_TYPE_U4:
838         case MONO_TYPE_I8:
839         case MONO_TYPE_U8:
840         case MONO_TYPE_R4:
841         case MONO_TYPE_R8:
842         case MONO_TYPE_I:
843         case MONO_TYPE_U:
844         case MONO_TYPE_STRING:
845         case MONO_TYPE_OBJECT:
846         case MONO_TYPE_TYPEDBYREF:
847                 sigbuffer_add_value (buf, type->type);
848                 break;
849         case MONO_TYPE_PTR:
850                 sigbuffer_add_value (buf, type->type);
851                 encode_type (assembly, type->data.type, buf);
852                 break;
853         case MONO_TYPE_SZARRAY:
854                 sigbuffer_add_value (buf, type->type);
855                 encode_type (assembly, &type->data.klass->byval_arg, buf);
856                 break;
857         case MONO_TYPE_VALUETYPE:
858         case MONO_TYPE_CLASS: {
859                 MonoClass *k = mono_class_from_mono_type (type);
860
861                 if (k->generic_container) {
862                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863                         encode_generic_class (assembly, gclass, buf);
864                 } else {
865                         /*
866                          * Make sure we use the correct type.
867                          */
868                         sigbuffer_add_value (buf, k->byval_arg.type);
869                         /*
870                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871                          * otherwise two typerefs could point to the same type, leading to
872                          * verification errors.
873                          */
874                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
875                 }
876                 break;
877         }
878         case MONO_TYPE_ARRAY:
879                 sigbuffer_add_value (buf, type->type);
880                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881                 sigbuffer_add_value (buf, type->data.array->rank);
882                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883                 sigbuffer_add_value (buf, 0);
884                 break;
885         case MONO_TYPE_GENERICINST:
886                 encode_generic_class (assembly, type->data.generic_class, buf);
887                 break;
888         case MONO_TYPE_VAR:
889         case MONO_TYPE_MVAR:
890                 sigbuffer_add_value (buf, type->type);
891                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
892                 break;
893         default:
894                 g_error ("need to encode type %x", type->type);
895         }
896 }
897
898 static void
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
900 {
901         MONO_REQ_GC_UNSAFE_MODE;
902
903         if (!type) {
904                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
905                 return;
906         }
907
908         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
909 }
910
911 static void
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
913 {
914         MONO_REQ_GC_UNSAFE_MODE;
915
916         int i;
917
918         if (modreq) {
919                 for (i = 0; i < mono_array_length (modreq); ++i) {
920                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
923                 }
924         }
925         if (modopt) {
926                 for (i = 0; i < mono_array_length (modopt); ++i) {
927                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
930                 }
931         }
932 }
933
934 #ifndef DISABLE_REFLECTION_EMIT
935 static guint32
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
937 {
938         MONO_REQ_GC_UNSAFE_MODE;
939
940         SigBuffer buf;
941         int i;
942         guint32 nparams =  sig->param_count;
943         guint32 idx;
944
945         if (!assembly->save)
946                 return 0;
947
948         sigbuffer_init (&buf, 32);
949         /*
950          * FIXME: vararg, explicit_this, differenc call_conv values...
951          */
952         idx = sig->call_convention;
953         if (sig->hasthis)
954                 idx |= 0x20; /* hasthis */
955         if (sig->generic_param_count)
956                 idx |= 0x10; /* generic */
957         sigbuffer_add_byte (&buf, idx);
958         if (sig->generic_param_count)
959                 sigbuffer_add_value (&buf, sig->generic_param_count);
960         sigbuffer_add_value (&buf, nparams);
961         encode_type (assembly, sig->ret, &buf);
962         for (i = 0; i < nparams; ++i) {
963                 if (i == sig->sentinelpos)
964                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965                 encode_type (assembly, sig->params [i], &buf);
966         }
967         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968         sigbuffer_free (&buf);
969         return idx;
970 }
971 #endif
972
973 static guint32
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
975 {
976         MONO_REQ_GC_UNSAFE_MODE;
977
978         /*
979          * FIXME: reuse code from method_encode_signature().
980          */
981         SigBuffer buf;
982         int i;
983         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
984         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
986         guint32 idx;
987
988         sigbuffer_init (&buf, 32);
989         /* LAMESPEC: all the call conv spec is foobared */
990         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991         if (mb->call_conv & 2)
992                 idx |= 0x5; /* vararg */
993         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994                 idx |= 0x20; /* hasthis */
995         if (ngparams)
996                 idx |= 0x10; /* generic */
997         sigbuffer_add_byte (&buf, idx);
998         if (ngparams)
999                 sigbuffer_add_value (&buf, ngparams);
1000         sigbuffer_add_value (&buf, nparams + notypes);
1001         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002         encode_reflection_type (assembly, mb->rtype, &buf);
1003         for (i = 0; i < nparams; ++i) {
1004                 MonoArray *modreq = NULL;
1005                 MonoArray *modopt = NULL;
1006                 MonoReflectionType *pt;
1007
1008                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014                 encode_reflection_type (assembly, pt, &buf);
1015         }
1016         if (notypes)
1017                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018         for (i = 0; i < notypes; ++i) {
1019                 MonoReflectionType *pt;
1020
1021                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022                 encode_reflection_type (assembly, pt, &buf);
1023         }
1024
1025         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026         sigbuffer_free (&buf);
1027         return idx;
1028 }
1029
1030 static guint32
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1032 {
1033         MONO_REQ_GC_UNSAFE_MODE;
1034
1035         MonoDynamicTable *table;
1036         guint32 *values;
1037         guint32 idx, sig_idx;
1038         guint nl = mono_array_length (ilgen->locals);
1039         SigBuffer buf;
1040         int i;
1041
1042         sigbuffer_init (&buf, 32);
1043         sigbuffer_add_value (&buf, 0x07);
1044         sigbuffer_add_value (&buf, nl);
1045         for (i = 0; i < nl; ++i) {
1046                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1047                 
1048                 if (lb->is_pinned)
1049                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1050                 
1051                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1052         }
1053         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054         sigbuffer_free (&buf);
1055
1056         if (assembly->standalonesig_cache == NULL)
1057                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1059         if (idx)
1060                 return idx;
1061
1062         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063         idx = table->next_idx ++;
1064         table->rows ++;
1065         alloc_table (table, table->rows);
1066         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1067
1068         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1069
1070         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1071
1072         return idx;
1073 }
1074
1075 static guint32
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1077 {
1078         MONO_REQ_GC_UNSAFE_MODE;
1079
1080         guint32 num_clauses = 0;
1081         int i;
1082
1083         MonoILExceptionInfo *ex_info;
1084         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086                 if (ex_info->handlers)
1087                         num_clauses += mono_array_length (ex_info->handlers);
1088                 else
1089                         num_clauses++;
1090         }
1091
1092         return num_clauses;
1093 }
1094
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1098 {
1099         MONO_REQ_GC_UNSAFE_MODE;
1100
1101         MonoExceptionClause *clauses;
1102         MonoExceptionClause *clause;
1103         MonoILExceptionInfo *ex_info;
1104         MonoILExceptionBlock *ex_block;
1105         guint32 finally_start;
1106         int i, j, clause_index;;
1107
1108         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1109
1110         clause_index = 0;
1111         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113                 finally_start = ex_info->start + ex_info->len;
1114                 if (!ex_info->handlers)
1115                         continue;
1116                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118                         clause = &(clauses [clause_index]);
1119
1120                         clause->flags = ex_block->type;
1121                         clause->try_offset = ex_info->start;
1122
1123                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124                                 clause->try_len = finally_start - ex_info->start;
1125                         else
1126                                 clause->try_len = ex_info->len;
1127                         clause->handler_offset = ex_block->start;
1128                         clause->handler_len = ex_block->len;
1129                         if (ex_block->extype) {
1130                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1131                         } else {
1132                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133                                         clause->data.filter_offset = ex_block->filter_offset;
1134                                 else
1135                                         clause->data.filter_offset = 0;
1136                         }
1137                         finally_start = ex_block->start + ex_block->len;
1138
1139                         clause_index ++;
1140                 }
1141         }
1142
1143         return clauses;
1144 }
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1146
1147 /**
1148  * method_encode_code:
1149  *
1150  * @assembly the assembly
1151  * @mb the managed MethodBuilder
1152  * @error set on error
1153  *
1154  * Note that the return value is not sensible if @error is set.
1155  */
1156 static guint32
1157 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1158 {
1159         MONO_REQ_GC_UNSAFE_MODE;
1160
1161         char flags = 0;
1162         guint32 idx;
1163         guint32 code_size;
1164         gint32 max_stack, i;
1165         gint32 num_locals = 0;
1166         gint32 num_exception = 0;
1167         gint maybe_small;
1168         guint32 fat_flags;
1169         char fat_header [12];
1170         guint32 int_value;
1171         guint16 short_value;
1172         guint32 local_sig = 0;
1173         guint32 header_size = 12;
1174         MonoArray *code;
1175
1176         mono_error_init (error);
1177
1178         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1179                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1180                 return 0;
1181
1182         /*if (mb->name)
1183                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1184         if (mb->ilgen) {
1185                 code = mb->ilgen->code;
1186                 code_size = mb->ilgen->code_len;
1187                 max_stack = mb->ilgen->max_stack;
1188                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1189                 if (mb->ilgen->ex_handlers)
1190                         num_exception = method_count_clauses (mb->ilgen);
1191         } else {
1192                 code = mb->code;
1193                 if (code == NULL){
1194                         char *name = mono_string_to_utf8 (mb->name);
1195                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1196                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1197                         g_free (str);
1198                         g_free (name);
1199                         return 0;
1200                 }
1201
1202                 code_size = mono_array_length (code);
1203                 max_stack = 8; /* we probably need to run a verifier on the code... */
1204         }
1205
1206         stream_data_align (&assembly->code);
1207
1208         /* check for exceptions, maxstack, locals */
1209         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1210         if (maybe_small) {
1211                 if (code_size < 64 && !(code_size & 1)) {
1212                         flags = (code_size << 2) | 0x2;
1213                 } else if (code_size < 32 && (code_size & 1)) {
1214                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1215                 } else {
1216                         goto fat_header;
1217                 }
1218                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1219                 /* add to the fixup todo list */
1220                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1221                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1222                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1223                 return assembly->text_rva + idx;
1224         } 
1225 fat_header:
1226         if (num_locals)
1227                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1228         /* 
1229          * FIXME: need to set also the header size in fat_flags.
1230          * (and more sects and init locals flags)
1231          */
1232         fat_flags =  0x03;
1233         if (num_exception)
1234                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1235         if (mb->init_locals)
1236                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1237         fat_header [0] = fat_flags;
1238         fat_header [1] = (header_size / 4 ) << 4;
1239         short_value = GUINT16_TO_LE (max_stack);
1240         memcpy (fat_header + 2, &short_value, 2);
1241         int_value = GUINT32_TO_LE (code_size);
1242         memcpy (fat_header + 4, &int_value, 4);
1243         int_value = GUINT32_TO_LE (local_sig);
1244         memcpy (fat_header + 8, &int_value, 4);
1245         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1246         /* add to the fixup todo list */
1247         if (mb->ilgen && mb->ilgen->num_token_fixups)
1248                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1249         
1250         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1251         if (num_exception) {
1252                 unsigned char sheader [4];
1253                 MonoILExceptionInfo * ex_info;
1254                 MonoILExceptionBlock * ex_block;
1255                 int j;
1256
1257                 stream_data_align (&assembly->code);
1258                 /* always use fat format for now */
1259                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1260                 num_exception *= 6 * sizeof (guint32);
1261                 num_exception += 4; /* include the size of the header */
1262                 sheader [1] = num_exception & 0xff;
1263                 sheader [2] = (num_exception >> 8) & 0xff;
1264                 sheader [3] = (num_exception >> 16) & 0xff;
1265                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1266                 /* fat header, so we are already aligned */
1267                 /* reverse order */
1268                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1269                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1270                         if (ex_info->handlers) {
1271                                 int finally_start = ex_info->start + ex_info->len;
1272                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1273                                         guint32 val;
1274                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1275                                         /* the flags */
1276                                         val = GUINT32_TO_LE (ex_block->type);
1277                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1278                                         /* try offset */
1279                                         val = GUINT32_TO_LE (ex_info->start);
1280                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1281                                         /* need fault, too, probably */
1282                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1283                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1284                                         else
1285                                                 val = GUINT32_TO_LE (ex_info->len);
1286                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1287                                         /* handler offset */
1288                                         val = GUINT32_TO_LE (ex_block->start);
1289                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1290                                         /* handler len */
1291                                         val = GUINT32_TO_LE (ex_block->len);
1292                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293                                         finally_start = ex_block->start + ex_block->len;
1294                                         if (ex_block->extype) {
1295                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1296                                         } else {
1297                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1298                                                         val = ex_block->filter_offset;
1299                                                 else
1300                                                         val = 0;
1301                                         }
1302                                         val = GUINT32_TO_LE (val);
1303                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1304                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1305                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1306                                 }
1307                         } else {
1308                                 g_error ("No clauses for ex info block %d", i);
1309                         }
1310                 }
1311         }
1312         return assembly->text_rva + idx;
1313 }
1314
1315 static guint32
1316 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1317 {
1318         MONO_REQ_GC_NEUTRAL_MODE;
1319
1320         int i;
1321         MonoDynamicTable *table;
1322         guint32 *values;
1323         
1324         table = &assembly->tables [table_idx];
1325
1326         g_assert (col < table->columns);
1327
1328         values = table->values + table->columns;
1329         for (i = 1; i <= table->rows; ++i) {
1330                 if (values [col] == token)
1331                         return i;
1332                 values += table->columns;
1333         }
1334         return 0;
1335 }
1336
1337 /*
1338  * LOCKING: Acquires the loader lock. 
1339  */
1340 static MonoCustomAttrInfo*
1341 lookup_custom_attr (MonoImage *image, gpointer member)
1342 {
1343         MONO_REQ_GC_NEUTRAL_MODE;
1344
1345         MonoCustomAttrInfo* res;
1346
1347         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1348
1349         if (!res)
1350                 return NULL;
1351
1352         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1353         res->cached = 0;
1354         return res;
1355 }
1356
1357 static gboolean
1358 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1359 {
1360         MONO_REQ_GC_UNSAFE_MODE;
1361
1362         /* FIXME: Need to do more checks */
1363         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1364                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1365
1366                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1367                         return FALSE;
1368         }
1369
1370         return TRUE;
1371 }
1372
1373 static MonoCustomAttrInfo*
1374 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1375 {
1376         MONO_REQ_GC_UNSAFE_MODE;
1377
1378         int i, index, count, not_visible;
1379         MonoCustomAttrInfo *ainfo;
1380         MonoReflectionCustomAttr *cattr;
1381
1382         if (!cattrs)
1383                 return NULL;
1384         /* FIXME: check in assembly the Run flag is set */
1385
1386         count = mono_array_length (cattrs);
1387
1388         /* Skip nonpublic attributes since MS.NET seems to do the same */
1389         /* FIXME: This needs to be done more globally */
1390         not_visible = 0;
1391         for (i = 0; i < count; ++i) {
1392                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1393                 if (!custom_attr_visible (image, cattr))
1394                         not_visible ++;
1395         }
1396         count -= not_visible;
1397
1398         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1399
1400         ainfo->image = image;
1401         ainfo->num_attrs = count;
1402         ainfo->cached = alloc_img != NULL;
1403         index = 0;
1404         for (i = 0; i < count; ++i) {
1405                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1406                 if (custom_attr_visible (image, cattr)) {
1407                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1408                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1409                         ainfo->attrs [index].ctor = cattr->ctor->method;
1410                         ainfo->attrs [index].data = saved;
1411                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1412                         index ++;
1413                 }
1414         }
1415
1416         return ainfo;
1417 }
1418
1419 #ifndef DISABLE_REFLECTION_EMIT
1420 /*
1421  * LOCKING: Acquires the loader lock. 
1422  */
1423 static void
1424 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1425 {
1426         MONO_REQ_GC_UNSAFE_MODE;
1427
1428         MonoCustomAttrInfo *ainfo, *tmp;
1429
1430         if (!cattrs || !mono_array_length (cattrs))
1431                 return;
1432
1433         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1434
1435         mono_loader_lock ();
1436         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1437         if (tmp)
1438                 mono_custom_attrs_free (tmp);
1439         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1440         mono_loader_unlock ();
1441
1442 }
1443 #endif
1444
1445 void
1446 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1447 {
1448         MONO_REQ_GC_NEUTRAL_MODE;
1449
1450         if (!ainfo->cached)
1451                 g_free (ainfo);
1452 }
1453
1454 /*
1455  * idx is the table index of the object
1456  * type is one of MONO_CUSTOM_ATTR_*
1457  */
1458 static gboolean
1459 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1460 {
1461         MONO_REQ_GC_UNSAFE_MODE;
1462
1463         MonoDynamicTable *table;
1464         MonoReflectionCustomAttr *cattr;
1465         guint32 *values;
1466         guint32 count, i, token;
1467         char blob_size [6];
1468         char *p = blob_size;
1469         
1470         mono_error_init (error);
1471
1472         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1473         if (!cattrs)
1474                 return TRUE;
1475         count = mono_array_length (cattrs);
1476         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1477         table->rows += count;
1478         alloc_table (table, table->rows);
1479         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1480         idx <<= MONO_CUSTOM_ATTR_BITS;
1481         idx |= type;
1482         for (i = 0; i < count; ++i) {
1483                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1485                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1486                 if (!mono_error_ok (error)) goto fail;
1487                 type = mono_metadata_token_index (token);
1488                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1489                 switch (mono_metadata_token_table (token)) {
1490                 case MONO_TABLE_METHOD:
1491                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1492                         /*
1493                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1494                          * method, not the one returned by mono_image_create_token ().
1495                          */
1496                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1497                         break;
1498                 case MONO_TABLE_MEMBERREF:
1499                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1500                         break;
1501                 default:
1502                         g_warning ("got wrong token in custom attr");
1503                         continue;
1504                 }
1505                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1506                 p = blob_size;
1507                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1508                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1509                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1510                 values += MONO_CUSTOM_ATTR_SIZE;
1511                 ++table->next_idx;
1512         }
1513
1514         return TRUE;
1515
1516 fail:
1517         return FALSE;
1518 }
1519
1520 static void
1521 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1522 {
1523         MONO_REQ_GC_UNSAFE_MODE;
1524
1525         MonoDynamicTable *table;
1526         guint32 *values;
1527         guint32 count, i, idx;
1528         MonoReflectionPermissionSet *perm;
1529
1530         if (!permissions)
1531                 return;
1532
1533         count = mono_array_length (permissions);
1534         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1535         table->rows += count;
1536         alloc_table (table, table->rows);
1537
1538         for (i = 0; i < mono_array_length (permissions); ++i) {
1539                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1540
1541                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1542
1543                 idx = mono_metadata_token_index (parent_token);
1544                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1545                 switch (mono_metadata_token_table (parent_token)) {
1546                 case MONO_TABLE_TYPEDEF:
1547                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1548                         break;
1549                 case MONO_TABLE_METHOD:
1550                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1551                         break;
1552                 case MONO_TABLE_ASSEMBLY:
1553                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1554                         break;
1555                 default:
1556                         g_assert_not_reached ();
1557                 }
1558
1559                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1560                 values [MONO_DECL_SECURITY_PARENT] = idx;
1561                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1562
1563                 ++table->next_idx;
1564         }
1565 }
1566
1567 /*
1568  * Fill in the MethodDef and ParamDef tables for a method.
1569  * This is used for both normal methods and constructors.
1570  */
1571 static gboolean
1572 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1573 {
1574         MONO_REQ_GC_UNSAFE_MODE;
1575
1576         MonoDynamicTable *table;
1577         guint32 *values;
1578         guint i, count;
1579
1580         mono_error_init (error);
1581
1582         /* room in this table is already allocated */
1583         table = &assembly->tables [MONO_TABLE_METHOD];
1584         *mb->table_idx = table->next_idx ++;
1585         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1586         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1587         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1588         values [MONO_METHOD_FLAGS] = mb->attrs;
1589         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1590         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1591         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1592         if (!mono_error_ok (error))
1593                 return FALSE;
1594
1595         table = &assembly->tables [MONO_TABLE_PARAM];
1596         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1597
1598         mono_image_add_decl_security (assembly, 
1599                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1600
1601         if (mb->pinfo) {
1602                 MonoDynamicTable *mtable;
1603                 guint32 *mvalues;
1604                 
1605                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1606                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1607                 
1608                 count = 0;
1609                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1610                         if (mono_array_get (mb->pinfo, gpointer, i))
1611                                 count++;
1612                 }
1613                 table->rows += count;
1614                 alloc_table (table, table->rows);
1615                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1616                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1617                         MonoReflectionParamBuilder *pb;
1618                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1619                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1620                                 values [MONO_PARAM_SEQUENCE] = i;
1621                                 if (pb->name != NULL) {
1622                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1623                                 } else {
1624                                         values [MONO_PARAM_NAME] = 0;
1625                                 }
1626                                 values += MONO_PARAM_SIZE;
1627                                 if (pb->marshal_info) {
1628                                         mtable->rows++;
1629                                         alloc_table (mtable, mtable->rows);
1630                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1631                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1632                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1633                                 }
1634                                 pb->table_idx = table->next_idx++;
1635                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1636                                         guint32 field_type = 0;
1637                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1638                                         mtable->rows ++;
1639                                         alloc_table (mtable, mtable->rows);
1640                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1641                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1642                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1643                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1644                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1645                                 }
1646                         }
1647                 }
1648         }
1649
1650         return TRUE;
1651 }
1652
1653 #ifndef DISABLE_REFLECTION_EMIT
1654 static gboolean
1655 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1656 {
1657         MONO_REQ_GC_UNSAFE_MODE;
1658
1659         mono_error_init (error);
1660         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1661
1662         rmb->ilgen = mb->ilgen;
1663         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1664         return_val_if_nok (error, FALSE);
1665         rmb->parameters = mb->parameters;
1666         rmb->generic_params = mb->generic_params;
1667         rmb->generic_container = mb->generic_container;
1668         rmb->opt_types = NULL;
1669         rmb->pinfo = mb->pinfo;
1670         rmb->attrs = mb->attrs;
1671         rmb->iattrs = mb->iattrs;
1672         rmb->call_conv = mb->call_conv;
1673         rmb->code = mb->code;
1674         rmb->type = mb->type;
1675         rmb->name = mb->name;
1676         rmb->table_idx = &mb->table_idx;
1677         rmb->init_locals = mb->init_locals;
1678         rmb->skip_visibility = FALSE;
1679         rmb->return_modreq = mb->return_modreq;
1680         rmb->return_modopt = mb->return_modopt;
1681         rmb->param_modreq = mb->param_modreq;
1682         rmb->param_modopt = mb->param_modopt;
1683         rmb->permissions = mb->permissions;
1684         rmb->mhandle = mb->mhandle;
1685         rmb->nrefs = 0;
1686         rmb->refs = NULL;
1687
1688         if (mb->dll) {
1689                 rmb->charset = mb->charset;
1690                 rmb->extra_flags = mb->extra_flags;
1691                 rmb->native_cc = mb->native_cc;
1692                 rmb->dllentry = mb->dllentry;
1693                 rmb->dll = mb->dll;
1694         }
1695
1696         return TRUE;
1697 }
1698
1699 static gboolean
1700 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1701 {
1702         MONO_REQ_GC_UNSAFE_MODE;
1703
1704         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1705
1706         mono_error_init (error);
1707
1708         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1709
1710         rmb->ilgen = mb->ilgen;
1711         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1712         return_val_if_nok (error, FALSE);
1713         rmb->parameters = mb->parameters;
1714         rmb->generic_params = NULL;
1715         rmb->generic_container = NULL;
1716         rmb->opt_types = NULL;
1717         rmb->pinfo = mb->pinfo;
1718         rmb->attrs = mb->attrs;
1719         rmb->iattrs = mb->iattrs;
1720         rmb->call_conv = mb->call_conv;
1721         rmb->code = NULL;
1722         rmb->type = mb->type;
1723         rmb->name = mono_string_new (mono_domain_get (), name);
1724         rmb->table_idx = &mb->table_idx;
1725         rmb->init_locals = mb->init_locals;
1726         rmb->skip_visibility = FALSE;
1727         rmb->return_modreq = NULL;
1728         rmb->return_modopt = NULL;
1729         rmb->param_modreq = mb->param_modreq;
1730         rmb->param_modopt = mb->param_modopt;
1731         rmb->permissions = mb->permissions;
1732         rmb->mhandle = mb->mhandle;
1733         rmb->nrefs = 0;
1734         rmb->refs = NULL;
1735
1736         return TRUE;
1737 }
1738
1739 static void
1740 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1741 {
1742         MONO_REQ_GC_UNSAFE_MODE;
1743
1744         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1745
1746         rmb->ilgen = mb->ilgen;
1747         rmb->rtype = mb->rtype;
1748         rmb->parameters = mb->parameters;
1749         rmb->generic_params = NULL;
1750         rmb->generic_container = NULL;
1751         rmb->opt_types = NULL;
1752         rmb->pinfo = NULL;
1753         rmb->attrs = mb->attrs;
1754         rmb->iattrs = 0;
1755         rmb->call_conv = mb->call_conv;
1756         rmb->code = NULL;
1757         rmb->type = (MonoObject *) mb->owner;
1758         rmb->name = mb->name;
1759         rmb->table_idx = NULL;
1760         rmb->init_locals = mb->init_locals;
1761         rmb->skip_visibility = mb->skip_visibility;
1762         rmb->return_modreq = NULL;
1763         rmb->return_modopt = NULL;
1764         rmb->param_modreq = NULL;
1765         rmb->param_modopt = NULL;
1766         rmb->permissions = NULL;
1767         rmb->mhandle = mb->mhandle;
1768         rmb->nrefs = 0;
1769         rmb->refs = NULL;
1770 }       
1771 #endif
1772
1773 static gboolean
1774 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1775 {
1776         MONO_REQ_GC_UNSAFE_MODE;
1777
1778         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1779         MonoDynamicTable *table;
1780         guint32 *values;
1781         guint32 tok;
1782         MonoReflectionMethod *m;
1783         int i;
1784
1785         mono_error_init (error);
1786
1787         if (!mb->override_methods)
1788                 return TRUE;
1789
1790         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1791                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1792
1793                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1794                 table->rows ++;
1795                 alloc_table (table, table->rows);
1796                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1797                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1798                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1799
1800                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1801                 return_val_if_nok (error, FALSE);
1802
1803                 switch (mono_metadata_token_table (tok)) {
1804                 case MONO_TABLE_MEMBERREF:
1805                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1806                         break;
1807                 case MONO_TABLE_METHOD:
1808                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1809                         break;
1810                 default:
1811                         g_assert_not_reached ();
1812                 }
1813                 values [MONO_METHODIMPL_DECLARATION] = tok;
1814         }
1815
1816         return TRUE;
1817 }
1818
1819 #ifndef DISABLE_REFLECTION_EMIT
1820 static void
1821 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1822 {
1823         MONO_REQ_GC_UNSAFE_MODE;
1824
1825         MonoError error;
1826
1827         MonoDynamicTable *table;
1828         guint32 *values;
1829         ReflectionMethodBuilder rmb;
1830         int i;
1831
1832         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
1833                 mono_error_raise_exception (&error); /* FIXME don't raise here */
1834
1835         mono_image_basic_method (&rmb, assembly, &error);
1836         mono_error_raise_exception (&error); /* FIXME don't raise here */
1837         mb->table_idx = *rmb.table_idx;
1838
1839         if (mb->dll) { /* It's a P/Invoke method */
1840                 guint32 moduleref;
1841                 /* map CharSet values to on-disk values */
1842                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1843                 int extra_flags = mb->extra_flags;
1844                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1845                 table->rows ++;
1846                 alloc_table (table, table->rows);
1847                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1848                 
1849                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1850                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1851                 if (mb->dllentry)
1852                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1853                 else
1854                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1855                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1856                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1857                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1858                         table->rows ++;
1859                         alloc_table (table, table->rows);
1860                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1861                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1862                 }
1863         }
1864
1865         if (mb->generic_params) {
1866                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1867                 table->rows += mono_array_length (mb->generic_params);
1868                 alloc_table (table, table->rows);
1869                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1870                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1871
1872                         mono_image_get_generic_param_info (
1873                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1874                 }
1875         }
1876
1877 }
1878
1879 static gboolean
1880 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1881 {
1882         MONO_REQ_GC_UNSAFE_MODE;
1883
1884         ReflectionMethodBuilder rmb;
1885
1886         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1887                 return FALSE;
1888
1889         if (!mono_image_basic_method (&rmb, assembly, error))
1890                 return FALSE;
1891
1892         mb->table_idx = *rmb.table_idx;
1893
1894         return TRUE;
1895 }
1896 #endif
1897
1898 static char*
1899 type_get_fully_qualified_name (MonoType *type)
1900 {
1901         MONO_REQ_GC_NEUTRAL_MODE;
1902
1903         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1904 }
1905
1906 static char*
1907 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1908 {
1909         MONO_REQ_GC_UNSAFE_MODE;
1910
1911         MonoClass *klass;
1912         MonoAssembly *ta;
1913
1914         klass = mono_class_from_mono_type (type);
1915         if (!klass) 
1916                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1917         ta = klass->image->assembly;
1918         if (assembly_is_dynamic (ta) || (ta == ass)) {
1919                 if (klass->generic_class || klass->generic_container)
1920                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1921                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1922                 else
1923                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1924         }
1925
1926         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1927 }
1928
1929 #ifndef DISABLE_REFLECTION_EMIT
1930 /*field_image is the image to which the eventual custom mods have been encoded against*/
1931 static guint32
1932 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1933 {
1934         MONO_REQ_GC_NEUTRAL_MODE;
1935
1936         SigBuffer buf;
1937         guint32 idx, i, token;
1938
1939         if (!assembly->save)
1940                 return 0;
1941
1942         sigbuffer_init (&buf, 32);
1943         
1944         sigbuffer_add_value (&buf, 0x06);
1945         /* encode custom attributes before the type */
1946         if (type->num_mods) {
1947                 for (i = 0; i < type->num_mods; ++i) {
1948                         if (field_image) {
1949                                 MonoError error;
1950                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1951                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1952
1953                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1954                         } else {
1955                                 token = type->modifiers [i].token;
1956                         }
1957
1958                         if (type->modifiers [i].required)
1959                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1960                         else
1961                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1962
1963                         sigbuffer_add_value (&buf, token);
1964                 }
1965         }
1966         encode_type (assembly, type, &buf);
1967         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1968         sigbuffer_free (&buf);
1969         return idx;
1970 }
1971 #endif
1972
1973 static guint32
1974 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1975 {
1976         MONO_REQ_GC_UNSAFE_MODE;
1977
1978         SigBuffer buf;
1979         guint32 idx;
1980         guint32 typespec = 0;
1981         MonoType *type;
1982         MonoClass *klass;
1983
1984         init_type_builder_generics (fb->type);
1985
1986         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1987         klass = mono_class_from_mono_type (type);
1988
1989         sigbuffer_init (&buf, 32);
1990         
1991         sigbuffer_add_value (&buf, 0x06);
1992         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1993         /* encode custom attributes before the type */
1994
1995         if (klass->generic_container)
1996                 typespec = create_typespec (assembly, type);
1997
1998         if (typespec) {
1999                 MonoGenericClass *gclass;
2000                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2001                 encode_generic_class (assembly, gclass, &buf);
2002         } else {
2003                 encode_type (assembly, type, &buf);
2004         }
2005         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2006         sigbuffer_free (&buf);
2007         return idx;
2008 }
2009
2010 static guint32
2011 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2012 {
2013         MONO_REQ_GC_UNSAFE_MODE;
2014
2015         char blob_size [64];
2016         char *b = blob_size;
2017         char *box_val;
2018         char* buf;
2019         guint32 idx = 0, len = 0, dummy = 0;
2020
2021         buf = (char *)g_malloc (64);
2022         if (!val) {
2023                 *ret_type = MONO_TYPE_CLASS;
2024                 len = 4;
2025                 box_val = (char*)&dummy;
2026         } else {
2027                 box_val = ((char*)val) + sizeof (MonoObject);
2028                 *ret_type = val->vtable->klass->byval_arg.type;
2029         }
2030 handle_enum:
2031         switch (*ret_type) {
2032         case MONO_TYPE_BOOLEAN:
2033         case MONO_TYPE_U1:
2034         case MONO_TYPE_I1:
2035                 len = 1;
2036                 break;
2037         case MONO_TYPE_CHAR:
2038         case MONO_TYPE_U2:
2039         case MONO_TYPE_I2:
2040                 len = 2;
2041                 break;
2042         case MONO_TYPE_U4:
2043         case MONO_TYPE_I4:
2044         case MONO_TYPE_R4:
2045                 len = 4;
2046                 break;
2047         case MONO_TYPE_U8:
2048         case MONO_TYPE_I8:
2049                 len = 8;
2050                 break;
2051         case MONO_TYPE_R8:
2052                 len = 8;
2053                 break;
2054         case MONO_TYPE_VALUETYPE: {
2055                 MonoClass *klass = val->vtable->klass;
2056                 
2057                 if (klass->enumtype) {
2058                         *ret_type = mono_class_enum_basetype (klass)->type;
2059                         goto handle_enum;
2060                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2061                         len = 8;
2062                 } else 
2063                         g_error ("we can't encode valuetypes, we should have never reached this line");
2064                 break;
2065         }
2066         case MONO_TYPE_CLASS:
2067                 break;
2068         case MONO_TYPE_STRING: {
2069                 MonoString *str = (MonoString*)val;
2070                 /* there is no signature */
2071                 len = str->length * 2;
2072                 mono_metadata_encode_value (len, b, &b);
2073 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2074                 {
2075                         char *swapped = g_malloc (2 * mono_string_length (str));
2076                         const char *p = (const char*)mono_string_chars (str);
2077
2078                         swap_with_size (swapped, p, 2, mono_string_length (str));
2079                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2080                         g_free (swapped);
2081                 }
2082 #else
2083                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2084 #endif
2085
2086                 g_free (buf);
2087                 return idx;
2088         }
2089         case MONO_TYPE_GENERICINST:
2090                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2091                 goto handle_enum;
2092         default:
2093                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2094         }
2095
2096         /* there is no signature */
2097         mono_metadata_encode_value (len, b, &b);
2098 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2099         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2100         swap_with_size (blob_size, box_val, len, 1);
2101         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2102 #else
2103         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2104 #endif
2105
2106         g_free (buf);
2107         return idx;
2108 }
2109
2110 static guint32
2111 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2112 {
2113         MONO_REQ_GC_UNSAFE_MODE;
2114
2115         char *str;
2116         SigBuffer buf;
2117         guint32 idx, len;
2118
2119         sigbuffer_init (&buf, 32);
2120
2121         sigbuffer_add_value (&buf, minfo->type);
2122
2123         switch (minfo->type) {
2124         case MONO_NATIVE_BYVALTSTR:
2125         case MONO_NATIVE_BYVALARRAY:
2126                 sigbuffer_add_value (&buf, minfo->count);
2127                 break;
2128         case MONO_NATIVE_LPARRAY:
2129                 if (minfo->eltype || minfo->has_size) {
2130                         sigbuffer_add_value (&buf, minfo->eltype);
2131                         if (minfo->has_size) {
2132                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2133                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2134
2135                                 /* LAMESPEC: ElemMult is undocumented */
2136                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2137                         }
2138                 }
2139                 break;
2140         case MONO_NATIVE_SAFEARRAY:
2141                 if (minfo->eltype)
2142                         sigbuffer_add_value (&buf, minfo->eltype);
2143                 break;
2144         case MONO_NATIVE_CUSTOM:
2145                 if (minfo->guid) {
2146                         str = mono_string_to_utf8 (minfo->guid);
2147                         len = strlen (str);
2148                         sigbuffer_add_value (&buf, len);
2149                         sigbuffer_add_mem (&buf, str, len);
2150                         g_free (str);
2151                 } else {
2152                         sigbuffer_add_value (&buf, 0);
2153                 }
2154                 /* native type name */
2155                 sigbuffer_add_value (&buf, 0);
2156                 /* custom marshaler type name */
2157                 if (minfo->marshaltype || minfo->marshaltyperef) {
2158                         if (minfo->marshaltyperef)
2159                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2160                         else
2161                                 str = mono_string_to_utf8 (minfo->marshaltype);
2162                         len = strlen (str);
2163                         sigbuffer_add_value (&buf, len);
2164                         sigbuffer_add_mem (&buf, str, len);
2165                         g_free (str);
2166                 } else {
2167                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2168                         sigbuffer_add_value (&buf, 0);
2169                 }
2170                 if (minfo->mcookie) {
2171                         str = mono_string_to_utf8 (minfo->mcookie);
2172                         len = strlen (str);
2173                         sigbuffer_add_value (&buf, len);
2174                         sigbuffer_add_mem (&buf, str, len);
2175                         g_free (str);
2176                 } else {
2177                         sigbuffer_add_value (&buf, 0);
2178                 }
2179                 break;
2180         default:
2181                 break;
2182         }
2183         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2184         sigbuffer_free (&buf);
2185         return idx;
2186 }
2187
2188 static void
2189 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2190 {
2191         MONO_REQ_GC_UNSAFE_MODE;
2192
2193         MonoDynamicTable *table;
2194         guint32 *values;
2195
2196         /* maybe this fixup should be done in the C# code */
2197         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2198                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2199         table = &assembly->tables [MONO_TABLE_FIELD];
2200         fb->table_idx = table->next_idx ++;
2201         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2202         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2203         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2204         values [MONO_FIELD_FLAGS] = fb->attrs;
2205         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2206
2207         if (fb->offset != -1) {
2208                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2209                 table->rows ++;
2210                 alloc_table (table, table->rows);
2211                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2212                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2213                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2214         }
2215         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2216                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2217                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2218                 table->rows ++;
2219                 alloc_table (table, table->rows);
2220                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2221                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2222                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2223                 values [MONO_CONSTANT_TYPE] = field_type;
2224                 values [MONO_CONSTANT_PADDING] = 0;
2225         }
2226         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2227                 guint32 rva_idx;
2228                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2229                 table->rows ++;
2230                 alloc_table (table, table->rows);
2231                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2232                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2233                 /*
2234                  * We store it in the code section because it's simpler for now.
2235                  */
2236                 if (fb->rva_data) {
2237                         if (mono_array_length (fb->rva_data) >= 10)
2238                                 stream_data_align (&assembly->code);
2239                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2240                 } else
2241                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2242                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2243         }
2244         if (fb->marshal_info) {
2245                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2246                 table->rows ++;
2247                 alloc_table (table, table->rows);
2248                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2249                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2250                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2251         }
2252 }
2253
2254 static guint32
2255 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2256 {
2257         MONO_REQ_GC_UNSAFE_MODE;
2258
2259         SigBuffer buf;
2260         guint32 nparams = 0;
2261         MonoReflectionMethodBuilder *mb = fb->get_method;
2262         MonoReflectionMethodBuilder *smb = fb->set_method;
2263         guint32 idx, i;
2264
2265         if (mb && mb->parameters)
2266                 nparams = mono_array_length (mb->parameters);
2267         if (!mb && smb && smb->parameters)
2268                 nparams = mono_array_length (smb->parameters) - 1;
2269         sigbuffer_init (&buf, 32);
2270         if (fb->call_conv & 0x20)
2271                 sigbuffer_add_byte (&buf, 0x28);
2272         else
2273                 sigbuffer_add_byte (&buf, 0x08);
2274         sigbuffer_add_value (&buf, nparams);
2275         if (mb) {
2276                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2277                 for (i = 0; i < nparams; ++i) {
2278                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2279                         encode_reflection_type (assembly, pt, &buf);
2280                 }
2281         } else if (smb && smb->parameters) {
2282                 /* the property type is the last param */
2283                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2284                 for (i = 0; i < nparams; ++i) {
2285                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2286                         encode_reflection_type (assembly, pt, &buf);
2287                 }
2288         } else {
2289                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2290         }
2291
2292         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2293         sigbuffer_free (&buf);
2294         return idx;
2295 }
2296
2297 static void
2298 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2299 {
2300         MONO_REQ_GC_UNSAFE_MODE;
2301
2302         MonoDynamicTable *table;
2303         guint32 *values;
2304         guint num_methods = 0;
2305         guint32 semaidx;
2306
2307         /* 
2308          * we need to set things in the following tables:
2309          * PROPERTYMAP (info already filled in _get_type_info ())
2310          * PROPERTY    (rows already preallocated in _get_type_info ())
2311          * METHOD      (method info already done with the generic method code)
2312          * METHODSEMANTICS
2313          * CONSTANT
2314          */
2315         table = &assembly->tables [MONO_TABLE_PROPERTY];
2316         pb->table_idx = table->next_idx ++;
2317         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2318         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2319         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2320         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2321
2322         /* FIXME: we still don't handle 'other' methods */
2323         if (pb->get_method) num_methods ++;
2324         if (pb->set_method) num_methods ++;
2325
2326         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2327         table->rows += num_methods;
2328         alloc_table (table, table->rows);
2329
2330         if (pb->get_method) {
2331                 semaidx = table->next_idx ++;
2332                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2333                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2334                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2335                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2336         }
2337         if (pb->set_method) {
2338                 semaidx = table->next_idx ++;
2339                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2340                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2341                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2342                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2343         }
2344         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2345                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2346                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2347                 table->rows ++;
2348                 alloc_table (table, table->rows);
2349                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2350                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2351                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2352                 values [MONO_CONSTANT_TYPE] = field_type;
2353                 values [MONO_CONSTANT_PADDING] = 0;
2354         }
2355 }
2356
2357 static void
2358 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2359 {
2360         MONO_REQ_GC_UNSAFE_MODE;
2361
2362         MonoDynamicTable *table;
2363         guint32 *values;
2364         guint num_methods = 0;
2365         guint32 semaidx;
2366
2367         /* 
2368          * we need to set things in the following tables:
2369          * EVENTMAP (info already filled in _get_type_info ())
2370          * EVENT    (rows already preallocated in _get_type_info ())
2371          * METHOD      (method info already done with the generic method code)
2372          * METHODSEMANTICS
2373          */
2374         table = &assembly->tables [MONO_TABLE_EVENT];
2375         eb->table_idx = table->next_idx ++;
2376         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2377         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2378         values [MONO_EVENT_FLAGS] = eb->attrs;
2379         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2380
2381         /*
2382          * FIXME: we still don't handle 'other' methods 
2383          */
2384         if (eb->add_method) num_methods ++;
2385         if (eb->remove_method) num_methods ++;
2386         if (eb->raise_method) num_methods ++;
2387
2388         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2389         table->rows += num_methods;
2390         alloc_table (table, table->rows);
2391
2392         if (eb->add_method) {
2393                 semaidx = table->next_idx ++;
2394                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2395                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2396                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2397                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2398         }
2399         if (eb->remove_method) {
2400                 semaidx = table->next_idx ++;
2401                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2402                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2403                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2404                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2405         }
2406         if (eb->raise_method) {
2407                 semaidx = table->next_idx ++;
2408                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2409                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2410                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2411                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2412         }
2413 }
2414
2415 static void
2416 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2417 {
2418         MONO_REQ_GC_UNSAFE_MODE;
2419
2420         MonoDynamicTable *table;
2421         guint32 num_constraints, i;
2422         guint32 *values;
2423         guint32 table_idx;
2424
2425         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2426         num_constraints = gparam->iface_constraints ?
2427                 mono_array_length (gparam->iface_constraints) : 0;
2428         table->rows += num_constraints;
2429         if (gparam->base_type)
2430                 table->rows++;
2431         alloc_table (table, table->rows);
2432
2433         if (gparam->base_type) {
2434                 table_idx = table->next_idx ++;
2435                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2436
2437                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2438                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2439                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2440         }
2441
2442         for (i = 0; i < num_constraints; i++) {
2443                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2444                         gparam->iface_constraints, gpointer, i);
2445
2446                 table_idx = table->next_idx ++;
2447                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2448
2449                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2450                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2451                         assembly, mono_reflection_type_get_handle (constraint));
2452         }
2453 }
2454
2455 static void
2456 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2457 {
2458         MONO_REQ_GC_UNSAFE_MODE;
2459
2460         GenericParamTableEntry *entry;
2461
2462         /*
2463          * The GenericParam table must be sorted according to the `owner' field.
2464          * We need to do this sorting prior to writing the GenericParamConstraint
2465          * table, since we have to use the final GenericParam table indices there
2466          * and they must also be sorted.
2467          */
2468
2469         entry = g_new0 (GenericParamTableEntry, 1);
2470         entry->owner = owner;
2471         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2472         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2473         entry->gparam = gparam;
2474         
2475         g_ptr_array_add (assembly->gen_params, entry);
2476 }
2477
2478 static void
2479 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2480 {
2481         MONO_REQ_GC_UNSAFE_MODE;
2482
2483         MonoError error;
2484
2485         MonoDynamicTable *table;
2486         MonoGenericParam *param;
2487         guint32 *values;
2488         guint32 table_idx;
2489
2490         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2491         table_idx = table->next_idx ++;
2492         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2493
2494         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2495
2496         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2497         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2498         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2499         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2500
2501         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, &error))
2502                 goto fail;
2503
2504         encode_constraints (entry->gparam, table_idx, assembly);
2505         return;
2506
2507 fail:
2508         mono_error_raise_exception (&error); /* FIXME don't raise here */
2509 }
2510
2511 static guint32
2512 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2513 {
2514         MONO_REQ_GC_UNSAFE_MODE;
2515
2516         MonoDynamicTable *table;
2517         guint32 token;
2518         guint32 *values;
2519         guint32 cols [MONO_ASSEMBLY_SIZE];
2520         const char *pubkey;
2521         guint32 publen;
2522
2523         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2524                 return token;
2525
2526         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2527                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2528                 token = table->next_idx ++;
2529                 table->rows ++;
2530                 alloc_table (table, table->rows);
2531                 values = table->values + token * MONO_MODULEREF_SIZE;
2532                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2533
2534                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2535                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2536                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2537
2538                 return token;
2539         }
2540         
2541         if (assembly_is_dynamic (image->assembly))
2542                 /* FIXME: */
2543                 memset (cols, 0, sizeof (cols));
2544         else {
2545                 /* image->assembly->image is the manifest module */
2546                 image = image->assembly->image;
2547                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2548         }
2549
2550         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2551         token = table->next_idx ++;
2552         table->rows ++;
2553         alloc_table (table, table->rows);
2554         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2555         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2556         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2557         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2558         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2559         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2560         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2561         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2562         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2563
2564         if (strcmp ("", image->assembly->aname.culture)) {
2565                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2566                                 image->assembly->aname.culture);
2567         }
2568
2569         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2570                 guchar pubtoken [9];
2571                 pubtoken [0] = 8;
2572                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2573                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2574         } else {
2575                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2576         }
2577         token <<= MONO_RESOLUTION_SCOPE_BITS;
2578         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2579         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2580         return token;
2581 }
2582
2583 static guint32
2584 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2585 {
2586         MONO_REQ_GC_NEUTRAL_MODE;
2587
2588         MonoDynamicTable *table;
2589         guint32 *values;
2590         guint32 token;
2591         SigBuffer buf;
2592
2593         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2594                 return token;
2595
2596         sigbuffer_init (&buf, 32);
2597         switch (type->type) {
2598         case MONO_TYPE_FNPTR:
2599         case MONO_TYPE_PTR:
2600         case MONO_TYPE_SZARRAY:
2601         case MONO_TYPE_ARRAY:
2602         case MONO_TYPE_VAR:
2603         case MONO_TYPE_MVAR:
2604         case MONO_TYPE_GENERICINST:
2605                 encode_type (assembly, type, &buf);
2606                 break;
2607         case MONO_TYPE_CLASS:
2608         case MONO_TYPE_VALUETYPE: {
2609                 MonoClass *k = mono_class_from_mono_type (type);
2610                 if (!k || !k->generic_container) {
2611                         sigbuffer_free (&buf);
2612                         return 0;
2613                 }
2614                 encode_type (assembly, type, &buf);
2615                 break;
2616         }
2617         default:
2618                 sigbuffer_free (&buf);
2619                 return 0;
2620         }
2621
2622         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2623         if (assembly->save) {
2624                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2625                 alloc_table (table, table->rows + 1);
2626                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2627                 values [MONO_TYPESPEC_SIGNATURE] = token;
2628         }
2629         sigbuffer_free (&buf);
2630
2631         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2632         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2633         table->next_idx ++;
2634         return token;
2635 }
2636
2637 static guint32
2638 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2639 {
2640         MONO_REQ_GC_UNSAFE_MODE;
2641
2642         MonoDynamicTable *table;
2643         guint32 *values;
2644         guint32 token, scope, enclosing;
2645         MonoClass *klass;
2646
2647         /* if the type requires a typespec, we must try that first*/
2648         if (try_typespec && (token = create_typespec (assembly, type)))
2649                 return token;
2650         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2651         if (token)
2652                 return token;
2653         klass = mono_class_from_mono_type (type);
2654         if (!klass)
2655                 klass = mono_class_from_mono_type (type);
2656
2657         /*
2658          * If it's in the same module and not a generic type parameter:
2659          */
2660         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2661                         (type->type != MONO_TYPE_MVAR)) {
2662                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2663                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2664                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2665                 return token;
2666         }
2667
2668         if (klass->nested_in) {
2669                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2670                 /* get the typeref idx of the enclosing type */
2671                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2672                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2673         } else {
2674                 scope = resolution_scope_from_image (assembly, klass->image);
2675         }
2676         table = &assembly->tables [MONO_TABLE_TYPEREF];
2677         if (assembly->save) {
2678                 alloc_table (table, table->rows + 1);
2679                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2680                 values [MONO_TYPEREF_SCOPE] = scope;
2681                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2682                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2683         }
2684         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2685         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2686         table->next_idx ++;
2687         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2688         return token;
2689 }
2690
2691 /*
2692  * Despite the name, we handle also TypeSpec (with the above helper).
2693  */
2694 static guint32
2695 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2696 {
2697         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2698 }
2699
2700 #ifndef DISABLE_REFLECTION_EMIT
2701 static guint32
2702 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2703 {
2704         MONO_REQ_GC_NEUTRAL_MODE;
2705
2706         MonoDynamicTable *table;
2707         guint32 *values;
2708         guint32 token, pclass;
2709
2710         switch (parent & MONO_TYPEDEFORREF_MASK) {
2711         case MONO_TYPEDEFORREF_TYPEREF:
2712                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2713                 break;
2714         case MONO_TYPEDEFORREF_TYPESPEC:
2715                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2716                 break;
2717         case MONO_TYPEDEFORREF_TYPEDEF:
2718                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2719                 break;
2720         default:
2721                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2722                 return 0;
2723         }
2724         /* extract the index */
2725         parent >>= MONO_TYPEDEFORREF_BITS;
2726
2727         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2728
2729         if (assembly->save) {
2730                 alloc_table (table, table->rows + 1);
2731                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2732                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2733                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2734                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2735         }
2736
2737         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2738         table->next_idx ++;
2739
2740         return token;
2741 }
2742
2743 /*
2744  * Insert a memberef row into the metadata: the token that point to the memberref
2745  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2746  * mono_image_get_fieldref_token()).
2747  * The sig param is an index to an already built signature.
2748  */
2749 static guint32
2750 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2751 {
2752         MONO_REQ_GC_NEUTRAL_MODE;
2753
2754         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2755         return mono_image_add_memberef_row (assembly, parent, name, sig);
2756 }
2757
2758
2759 static guint32
2760 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2761 {
2762         MONO_REQ_GC_NEUTRAL_MODE;
2763
2764         guint32 token;
2765         MonoMethodSignature *sig;
2766         
2767         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2768
2769         if (create_typespec) {
2770                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2771                 if (token)
2772                         return token;
2773         } 
2774
2775         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2776         if (token && !create_typespec)
2777                 return token;
2778
2779         g_assert (!method->is_inflated);
2780         if (!token) {
2781                 /*
2782                  * A methodref signature can't contain an unmanaged calling convention.
2783                  */
2784                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2785                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2786                         sig->call_convention = MONO_CALL_DEFAULT;
2787                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2788                         method->name,  method_encode_signature (assembly, sig));
2789                 g_free (sig);
2790                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2791         }
2792
2793         if (create_typespec) {
2794                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2795                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2796                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2797
2798                 if (assembly->save) {
2799                         guint32 *values;
2800
2801                         alloc_table (table, table->rows + 1);
2802                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2803                         values [MONO_METHODSPEC_METHOD] = token;
2804                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2805                 }
2806
2807                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2808                 table->next_idx ++;
2809                 /*methodspec and memberef tokens are diferent, */
2810                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2811                 return token;
2812         }
2813         return token;
2814 }
2815
2816 static guint32
2817 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2818 {
2819         MonoError error;
2820         guint32 token, parent, sig;
2821         ReflectionMethodBuilder rmb;
2822         char *name;
2823         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2824         
2825         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2826         if (token)
2827                 return token;
2828
2829         name = mono_string_to_utf8 (method->name);
2830         if (!reflection_methodbuilder_from_method_builder (&rmb, method, &error))
2831                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2832
2833         /*
2834          * A methodref signature can't contain an unmanaged calling convention.
2835          * Since some flags are encoded as part of call_conv, we need to check against it.
2836         */
2837         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2838                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2839
2840         sig = method_builder_encode_signature (assembly, &rmb);
2841
2842         if (tb->generic_params)
2843                 parent = create_generic_typespec (assembly, tb);
2844         else
2845                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2846
2847         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2848
2849         g_free (name);
2850         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2851         return token;
2852 }
2853
2854 static guint32
2855 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2856                                      const gchar *name, guint32 sig)
2857 {
2858         MonoDynamicTable *table;
2859         guint32 token;
2860         guint32 *values;
2861         
2862         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2863
2864         if (assembly->save) {
2865                 alloc_table (table, table->rows + 1);
2866                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2867                 values [MONO_MEMBERREF_CLASS] = original;
2868                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2869                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2870         }
2871
2872         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2873         table->next_idx ++;
2874
2875         return token;
2876 }
2877
2878 static guint32
2879 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2880 {
2881         SigBuffer buf;
2882         int i;
2883         guint32 nparams = mono_array_length (mb->generic_params);
2884         guint32 idx;
2885
2886         if (!assembly->save)
2887                 return 0;
2888
2889         sigbuffer_init (&buf, 32);
2890
2891         sigbuffer_add_value (&buf, 0xa);
2892         sigbuffer_add_value (&buf, nparams);
2893
2894         for (i = 0; i < nparams; i++) {
2895                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2896                 sigbuffer_add_value (&buf, i);
2897         }
2898
2899         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2900         sigbuffer_free (&buf);
2901         return idx;
2902 }
2903
2904 static guint32
2905 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2906 {
2907         MonoDynamicTable *table;
2908         guint32 *values;
2909         guint32 token, mtoken = 0;
2910
2911         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2912         if (token)
2913                 return token;
2914
2915         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2916
2917         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2918         switch (mono_metadata_token_table (mtoken)) {
2919         case MONO_TABLE_MEMBERREF:
2920                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2921                 break;
2922         case MONO_TABLE_METHOD:
2923                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2924                 break;
2925         default:
2926                 g_assert_not_reached ();
2927         }
2928
2929         if (assembly->save) {
2930                 alloc_table (table, table->rows + 1);
2931                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2932                 values [MONO_METHODSPEC_METHOD] = mtoken;
2933                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2934         }
2935
2936         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2937         table->next_idx ++;
2938
2939         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2940         return token;
2941 }
2942
2943 static guint32
2944 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2945 {
2946         guint32 token;
2947
2948         if (mb->generic_params && create_methodspec) 
2949                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2950
2951         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2952         if (token)
2953                 return token;
2954
2955         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2956         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2957         return token;
2958 }
2959
2960 static guint32
2961 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2962 {
2963         MonoError error;
2964         guint32 token, parent, sig;
2965         ReflectionMethodBuilder rmb;
2966         char *name;
2967         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2968         
2969         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2970         if (token)
2971                 return token;
2972
2973         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, &error))
2974                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2975
2976         if (tb->generic_params)
2977                 parent = create_generic_typespec (assembly, tb);
2978         else
2979                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2980         
2981         name = mono_string_to_utf8 (rmb.name);
2982         sig = method_builder_encode_signature (assembly, &rmb);
2983
2984         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2985
2986         g_free (name);
2987         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2988         return token;
2989 }
2990 #endif
2991
2992 static gboolean
2993 is_field_on_inst (MonoClassField *field)
2994 {
2995         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2996 }
2997
2998 /*
2999  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3000  */
3001 static MonoType*
3002 get_field_on_inst_generic_type (MonoClassField *field)
3003 {
3004         MonoClass *klass, *gtd;
3005         MonoDynamicGenericClass *dgclass;
3006         int field_index;
3007
3008         g_assert (is_field_on_inst (field));
3009
3010         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3011
3012         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3013                 field_index = field - dgclass->fields;
3014                 return dgclass->field_generic_types [field_index];              
3015         }
3016
3017         klass = field->parent;
3018         gtd = klass->generic_class->container_class;
3019
3020         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3021                 field_index = field - klass->fields;
3022                 return gtd->fields [field_index].type;
3023         }
3024
3025         g_assert_not_reached ();
3026         return 0;
3027 }
3028
3029 #ifndef DISABLE_REFLECTION_EMIT
3030 static guint32
3031 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3032 {
3033         MonoType *type;
3034         guint32 token;
3035
3036         g_assert (field);
3037         g_assert (field->parent);
3038
3039         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3040         if (token)
3041                 return token;
3042
3043         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3044                 int index = field - field->parent->fields;
3045                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3046         } else {
3047                 if (is_field_on_inst (field))
3048                         type = get_field_on_inst_generic_type (field);
3049                 else
3050                         type = mono_field_get_type (field);
3051         }
3052         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3053                                                                                         mono_field_get_name (field),
3054                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3055         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3056         return token;
3057 }
3058
3059 static guint32
3060 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3061 {
3062         guint32 token;
3063         MonoClass *klass;
3064         MonoGenericClass *gclass;
3065         MonoType *type;
3066         char *name;
3067
3068         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3069         if (token)
3070                 return token;
3071         if (is_sre_field_builder (mono_object_class (f->fb))) {
3072                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3073                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3074                 klass = mono_class_from_mono_type (type);
3075                 gclass = type->data.generic_class;
3076                 g_assert (gclass->is_dynamic);
3077
3078                 name = mono_string_to_utf8 (fb->name);
3079                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3080                                                                                                 field_encode_signature (assembly, fb));
3081                 g_free (name);          
3082         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3083                 guint32 sig;
3084                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3085
3086                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3087                 klass = mono_class_from_mono_type (type);
3088
3089                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3090                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3091         } else {
3092                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3093                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3094         }
3095
3096         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3097         return token;
3098 }
3099
3100 static guint32
3101 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3102 {
3103         MonoError error;
3104         guint32 sig, token;
3105         MonoClass *klass;
3106         MonoGenericClass *gclass;
3107         MonoType *type;
3108
3109         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3110
3111         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3112         if (token)
3113                 return token;
3114
3115         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3116                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3117                 ReflectionMethodBuilder rmb;
3118                 char *name;
3119
3120                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3121                 klass = mono_class_from_mono_type (type);
3122
3123                 gclass = type->data.generic_class;
3124                 g_assert (gclass->is_dynamic);
3125
3126                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, &error))
3127                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3128
3129                 name = mono_string_to_utf8 (rmb.name);
3130
3131                 sig = method_builder_encode_signature (assembly, &rmb);
3132
3133                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3134                 g_free (name);
3135         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3136                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3137
3138                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3139                 klass = mono_class_from_mono_type (type);
3140
3141                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3142                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3143         } else {
3144                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3145                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3146         }
3147
3148
3149         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3150         return token;
3151 }
3152
3153 static MonoMethod*
3154 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3155 {
3156         MonoError error;
3157         MonoClass *klass;
3158         MonoGenericContext tmp_context;
3159         MonoType **type_argv;
3160         MonoGenericInst *ginst;
3161         MonoMethod *method, *inflated;
3162         int count, i;
3163
3164         init_type_builder_generics ((MonoObject*)m->inst);
3165
3166         method = inflate_method (m->inst, (MonoObject*)m->mb);
3167
3168         klass = method->klass;
3169
3170         if (m->method_args == NULL)
3171                 return method;
3172
3173         if (method->is_inflated)
3174                 method = ((MonoMethodInflated *) method)->declaring;
3175
3176         count = mono_array_length (m->method_args);
3177
3178         type_argv = g_new0 (MonoType *, count);
3179         for (i = 0; i < count; i++) {
3180                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3181                 type_argv [i] = mono_reflection_type_get_handle (garg);
3182         }
3183         ginst = mono_metadata_get_generic_inst (count, type_argv);
3184         g_free (type_argv);
3185
3186         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3187         tmp_context.method_inst = ginst;
3188
3189         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3190         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3191         return inflated;
3192 }
3193
3194 static guint32
3195 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3196 {
3197         MonoError error;
3198
3199         guint32 sig, token = 0;
3200         MonoType *type;
3201         MonoClass *klass;
3202
3203         if (m->method_args) {
3204                 MonoMethod *inflated;
3205
3206                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3207                 if (create_methodspec)
3208                         token = mono_image_get_methodspec_token (assembly, inflated);
3209                 else
3210                         token = mono_image_get_inflated_method_token (assembly, inflated);
3211                 return token;
3212         }
3213
3214         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3215         if (token)
3216                 return token;
3217
3218         if (is_sre_method_builder (mono_object_class (m->mb))) {
3219                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3220                 MonoGenericClass *gclass;
3221                 ReflectionMethodBuilder rmb;
3222                 char *name;
3223
3224                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3225                 klass = mono_class_from_mono_type (type);
3226                 gclass = type->data.generic_class;
3227                 g_assert (gclass->is_dynamic);
3228
3229                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
3230                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3231
3232                 name = mono_string_to_utf8 (rmb.name);
3233
3234                 sig = method_builder_encode_signature (assembly, &rmb);
3235
3236                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3237                 g_free (name);          
3238         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3239                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3240
3241                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3242                 klass = mono_class_from_mono_type (type);
3243
3244                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3245                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3246         } else {
3247                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3248                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3249         }
3250
3251         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3252         return token;
3253 }
3254
3255 static guint32
3256 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3257 {
3258         SigBuffer buf;
3259         int i;
3260         guint32 nparams = context->method_inst->type_argc;
3261         guint32 idx;
3262
3263         if (!assembly->save)
3264                 return 0;
3265
3266         sigbuffer_init (&buf, 32);
3267         /*
3268          * FIXME: vararg, explicit_this, differenc call_conv values...
3269          */
3270         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3271         sigbuffer_add_value (&buf, nparams);
3272
3273         for (i = 0; i < nparams; i++)
3274                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3275
3276         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3277         sigbuffer_free (&buf);
3278         return idx;
3279 }
3280
3281 static guint32
3282 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3283 {
3284         MonoDynamicTable *table;
3285         guint32 *values;
3286         guint32 token, mtoken = 0, sig;
3287         MonoMethodInflated *imethod;
3288         MonoMethod *declaring;
3289
3290         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3291
3292         g_assert (method->is_inflated);
3293         imethod = (MonoMethodInflated *) method;
3294         declaring = imethod->declaring;
3295
3296         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3297         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3298
3299         if (!mono_method_signature (declaring)->generic_param_count)
3300                 return mtoken;
3301
3302         switch (mono_metadata_token_table (mtoken)) {
3303         case MONO_TABLE_MEMBERREF:
3304                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3305                 break;
3306         case MONO_TABLE_METHOD:
3307                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3308                 break;
3309         default:
3310                 g_assert_not_reached ();
3311         }
3312
3313         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3314
3315         if (assembly->save) {
3316                 alloc_table (table, table->rows + 1);
3317                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3318                 values [MONO_METHODSPEC_METHOD] = mtoken;
3319                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3320         }
3321
3322         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3323         table->next_idx ++;
3324
3325         return token;
3326 }
3327
3328 static guint32
3329 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3330 {
3331         MonoMethodInflated *imethod;
3332         guint32 token;
3333         
3334         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3335         if (token)
3336                 return token;
3337
3338         g_assert (method->is_inflated);
3339         imethod = (MonoMethodInflated *) method;
3340
3341         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3342                 token = method_encode_methodspec (assembly, method);
3343         } else {
3344                 guint32 sig = method_encode_signature (
3345                         assembly, mono_method_signature (imethod->declaring));
3346                 token = mono_image_get_memberref_token (
3347                         assembly, &method->klass->byval_arg, method->name, sig);
3348         }
3349
3350         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3351         return token;
3352 }
3353
3354 static guint32
3355 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3356 {
3357         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3358         guint32 sig, token;
3359
3360         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3361         token = mono_image_get_memberref_token (
3362                 assembly, &m->klass->byval_arg, m->name, sig);
3363
3364         return token;
3365 }
3366
3367 static guint32
3368 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3369 {
3370         MonoDynamicTable *table;
3371         MonoClass *klass;
3372         MonoType *type;
3373         guint32 *values;
3374         guint32 token;
3375         SigBuffer buf;
3376         int count, i;
3377
3378         /*
3379          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3380          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3381          * Because of this, we must not insert it into the `typeref' hash table.
3382          */
3383         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3384         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3385         if (token)
3386                 return token;
3387
3388         sigbuffer_init (&buf, 32);
3389
3390         g_assert (tb->generic_params);
3391         klass = mono_class_from_mono_type (type);
3392
3393         if (tb->generic_container)
3394                 mono_reflection_create_generic_class (tb);
3395
3396         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3397         g_assert (klass->generic_container);
3398         sigbuffer_add_value (&buf, klass->byval_arg.type);
3399         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3400
3401         count = mono_array_length (tb->generic_params);
3402         sigbuffer_add_value (&buf, count);
3403         for (i = 0; i < count; i++) {
3404                 MonoReflectionGenericParam *gparam;
3405
3406                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3407
3408                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3409         }
3410
3411         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3412
3413         if (assembly->save) {
3414                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3415                 alloc_table (table, table->rows + 1);
3416                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3417                 values [MONO_TYPESPEC_SIGNATURE] = token;
3418         }
3419         sigbuffer_free (&buf);
3420
3421         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3422         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3423         table->next_idx ++;
3424         return token;
3425 }
3426
3427 /*
3428  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3429  */
3430 static MonoType*
3431 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3432 {
3433         int i, count, len, pos;
3434         MonoType *t;
3435
3436         count = 0;
3437         if (modreq)
3438                 count += mono_array_length (modreq);
3439         if (modopt)
3440                 count += mono_array_length (modopt);
3441
3442         if (count == 0)
3443                 return mono_metadata_type_dup (NULL, type);
3444
3445         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3446         t = (MonoType *)g_malloc (len);
3447         memcpy (t, type, MONO_SIZEOF_TYPE);
3448
3449         t->num_mods = count;
3450         pos = 0;
3451         if (modreq) {
3452                 for (i = 0; i < mono_array_length (modreq); ++i) {
3453                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3454                         t->modifiers [pos].required = 1;
3455                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3456                         pos ++;
3457                 }
3458         }
3459         if (modopt) {
3460                 for (i = 0; i < mono_array_length (modopt); ++i) {
3461                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3462                         t->modifiers [pos].required = 0;
3463                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3464                         pos ++;
3465                 }
3466         }
3467
3468         return t;
3469 }
3470
3471 static void
3472 init_type_builder_generics (MonoObject *type)
3473 {
3474         MonoReflectionTypeBuilder *tb;
3475
3476         if (!is_sre_type_builder(mono_object_class (type)))
3477                 return;
3478         tb = (MonoReflectionTypeBuilder *)type;
3479
3480         if (tb && tb->generic_container)
3481                 mono_reflection_create_generic_class (tb);
3482 }
3483
3484 static guint32
3485 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3486 {
3487         MonoDynamicTable *table;
3488         MonoType *custom = NULL, *type;
3489         guint32 *values;
3490         guint32 token, pclass, parent, sig;
3491         gchar *name;
3492
3493         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3494         if (token)
3495                 return token;
3496
3497         /* FIXME: is this call necessary? */
3498         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3499         name = mono_string_to_utf8 (fb->name);
3500
3501         /*FIXME this is one more layer of ugliness due how types are created.*/
3502         init_type_builder_generics (fb->type);
3503
3504         /* fb->type does not include the custom modifiers */
3505         /* FIXME: We should do this in one place when a fieldbuilder is created */
3506         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3507         if (fb->modreq || fb->modopt)
3508                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3509
3510         sig = fieldref_encode_signature (assembly, NULL, type);
3511         g_free (custom);
3512
3513         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3514         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3515         
3516         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3517         parent >>= MONO_TYPEDEFORREF_BITS;
3518
3519         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3520
3521         if (assembly->save) {
3522                 alloc_table (table, table->rows + 1);
3523                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3524                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3525                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3526                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3527         }
3528
3529         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3530         table->next_idx ++;
3531         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3532         g_free (name);
3533         return token;
3534 }
3535
3536 static guint32
3537 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3538 {
3539         SigBuffer buf;
3540         guint32 nargs;
3541         guint32 i, idx;
3542
3543         if (!assembly->save)
3544                 return 0;
3545
3546         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3547         g_assert (helper->type == 2);
3548
3549         if (helper->arguments)
3550                 nargs = mono_array_length (helper->arguments);
3551         else
3552                 nargs = 0;
3553
3554         sigbuffer_init (&buf, 32);
3555
3556         /* Encode calling convention */
3557         /* Change Any to Standard */
3558         if ((helper->call_conv & 0x03) == 0x03)
3559                 helper->call_conv = 0x01;
3560         /* explicit_this implies has_this */
3561         if (helper->call_conv & 0x40)
3562                 helper->call_conv &= 0x20;
3563
3564         if (helper->call_conv == 0) { /* Unmanaged */
3565                 idx = helper->unmanaged_call_conv - 1;
3566         } else {
3567                 /* Managed */
3568                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3569                 if (helper->call_conv & 0x02) /* varargs */
3570                         idx += 0x05;
3571         }
3572
3573         sigbuffer_add_byte (&buf, idx);
3574         sigbuffer_add_value (&buf, nargs);
3575         encode_reflection_type (assembly, helper->return_type, &buf);
3576         for (i = 0; i < nargs; ++i) {
3577                 MonoArray *modreqs = NULL;
3578                 MonoArray *modopts = NULL;
3579                 MonoReflectionType *pt;
3580
3581                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3582                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3583                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3584                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3585
3586                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3587                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3588                 encode_reflection_type (assembly, pt, &buf);
3589         }
3590         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3591         sigbuffer_free (&buf);
3592
3593         return idx;
3594 }
3595
3596 static guint32 
3597 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3598 {
3599         guint32 idx;
3600         MonoDynamicTable *table;
3601         guint32 *values;
3602
3603         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3604         idx = table->next_idx ++;
3605         table->rows ++;
3606         alloc_table (table, table->rows);
3607         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3608
3609         values [MONO_STAND_ALONE_SIGNATURE] =
3610                 mono_reflection_encode_sighelper (assembly, helper);
3611
3612         return idx;
3613 }
3614
3615 static int
3616 reflection_cc_to_file (int call_conv) {
3617         switch (call_conv & 0x3) {
3618         case 0:
3619         case 1: return MONO_CALL_DEFAULT;
3620         case 2: return MONO_CALL_VARARG;
3621         default:
3622                 g_assert_not_reached ();
3623         }
3624         return 0;
3625 }
3626 #endif /* !DISABLE_REFLECTION_EMIT */
3627
3628 typedef struct {
3629         MonoType *parent;
3630         MonoMethodSignature *sig;
3631         char *name;
3632         guint32 token;
3633 } ArrayMethod;
3634
3635 #ifndef DISABLE_REFLECTION_EMIT
3636 static guint32
3637 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3638 {
3639         guint32 nparams, i;
3640         GList *tmp;
3641         char *name;
3642         MonoMethodSignature *sig;
3643         ArrayMethod *am;
3644         MonoType *mtype;
3645
3646         name = mono_string_to_utf8 (m->name);
3647         nparams = mono_array_length (m->parameters);
3648         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3649         sig->hasthis = 1;
3650         sig->sentinelpos = -1;
3651         sig->call_convention = reflection_cc_to_file (m->call_conv);
3652         sig->param_count = nparams;
3653         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3654         mtype = mono_reflection_type_get_handle (m->parent);
3655         for (i = 0; i < nparams; ++i)
3656                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3657
3658         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3659                 am = (ArrayMethod *)tmp->data;
3660                 if (strcmp (name, am->name) == 0 && 
3661                                 mono_metadata_type_equal (am->parent, mtype) &&
3662                                 mono_metadata_signature_equal (am->sig, sig)) {
3663                         g_free (name);
3664                         g_free (sig);
3665                         m->table_idx = am->token & 0xffffff;
3666                         return am->token;
3667                 }
3668         }
3669         am = g_new0 (ArrayMethod, 1);
3670         am->name = name;
3671         am->sig = sig;
3672         am->parent = mtype;
3673         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3674                 method_encode_signature (assembly, sig));
3675         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3676         m->table_idx = am->token & 0xffffff;
3677         return am->token;
3678 }
3679
3680 /*
3681  * Insert into the metadata tables all the info about the TypeBuilder tb.
3682  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3683  */
3684 static void
3685 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3686 {
3687         MonoError error;
3688         MonoDynamicTable *table;
3689         guint *values;
3690         int i, is_object = 0, is_system = 0;
3691         char *n;
3692
3693         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3694         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3695         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3696         n = mono_string_to_utf8 (tb->name);
3697         if (strcmp (n, "Object") == 0)
3698                 is_object++;
3699         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3700         g_free (n);
3701         n = mono_string_to_utf8 (tb->nspace);
3702         if (strcmp (n, "System") == 0)
3703                 is_system++;
3704         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3705         g_free (n);
3706         if (tb->parent && !(is_system && is_object) && 
3707                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3708                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3709         } else {
3710                 values [MONO_TYPEDEF_EXTENDS] = 0;
3711         }
3712         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3713         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3714
3715         /*
3716          * if we have explicitlayout or sequentiallayouts, output data in the
3717          * ClassLayout table.
3718          */
3719         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3720                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3721                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3722                 table->rows++;
3723                 alloc_table (table, table->rows);
3724                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3725                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3726                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3727                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3728         }
3729
3730         /* handle interfaces */
3731         if (tb->interfaces) {
3732                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3733                 i = table->rows;
3734                 table->rows += mono_array_length (tb->interfaces);
3735                 alloc_table (table, table->rows);
3736                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3737                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3738                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3739                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3740                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3741                         values += MONO_INTERFACEIMPL_SIZE;
3742                 }
3743         }
3744
3745         /* handle fields */
3746         if (tb->fields) {
3747                 table = &assembly->tables [MONO_TABLE_FIELD];
3748                 table->rows += tb->num_fields;
3749                 alloc_table (table, table->rows);
3750                 for (i = 0; i < tb->num_fields; ++i)
3751                         mono_image_get_field_info (
3752                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3753         }
3754
3755         /* handle constructors */
3756         if (tb->ctors) {
3757                 table = &assembly->tables [MONO_TABLE_METHOD];
3758                 table->rows += mono_array_length (tb->ctors);
3759                 alloc_table (table, table->rows);
3760                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3761                         mono_image_get_ctor_info (domain,
3762                                                   mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3763                                                   assembly, &error);
3764                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3765                 }
3766         }
3767
3768         /* handle methods */
3769         if (tb->methods) {
3770                 table = &assembly->tables [MONO_TABLE_METHOD];
3771                 table->rows += tb->num_methods;
3772                 alloc_table (table, table->rows);
3773                 for (i = 0; i < tb->num_methods; ++i)
3774                         mono_image_get_method_info (
3775                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3776         }
3777
3778         /* Do the same with properties etc.. */
3779         if (tb->events && mono_array_length (tb->events)) {
3780                 table = &assembly->tables [MONO_TABLE_EVENT];
3781                 table->rows += mono_array_length (tb->events);
3782                 alloc_table (table, table->rows);
3783                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3784                 table->rows ++;
3785                 alloc_table (table, table->rows);
3786                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3787                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3788                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3789                 for (i = 0; i < mono_array_length (tb->events); ++i)
3790                         mono_image_get_event_info (
3791                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3792         }
3793         if (tb->properties && mono_array_length (tb->properties)) {
3794                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3795                 table->rows += mono_array_length (tb->properties);
3796                 alloc_table (table, table->rows);
3797                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3798                 table->rows ++;
3799                 alloc_table (table, table->rows);
3800                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3801                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3802                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3803                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3804                         mono_image_get_property_info (
3805                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3806         }
3807
3808         /* handle generic parameters */
3809         if (tb->generic_params) {
3810                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3811                 table->rows += mono_array_length (tb->generic_params);
3812                 alloc_table (table, table->rows);
3813                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3814                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3815
3816                         mono_image_get_generic_param_info (
3817                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3818                 }
3819         }
3820
3821         mono_image_add_decl_security (assembly, 
3822                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3823
3824         if (tb->subtypes) {
3825                 MonoDynamicTable *ntable;
3826                 
3827                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3828                 ntable->rows += mono_array_length (tb->subtypes);
3829                 alloc_table (ntable, ntable->rows);
3830                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3831
3832                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3833                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3834
3835                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3836                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3837                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3838                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3839                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3840                                 ntable->next_idx, ntable->rows);*/
3841                         values += MONO_NESTED_CLASS_SIZE;
3842                         ntable->next_idx++;
3843                 }
3844         }
3845 }
3846 #endif
3847
3848 static void
3849 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3850 {
3851         int i;
3852
3853         mono_ptr_array_append (*types, type);
3854
3855         if (!type->subtypes)
3856                 return;
3857
3858         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3859                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3860                 collect_types (types, subtype);
3861         }
3862 }
3863
3864 static gint
3865 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3866 {
3867         if ((*type1)->table_idx < (*type2)->table_idx)
3868                 return -1;
3869         else
3870                 if ((*type1)->table_idx > (*type2)->table_idx)
3871                         return 1;
3872         else
3873                 return 0;
3874 }
3875
3876 static gboolean
3877 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3878         int i;
3879
3880         mono_error_init (error);
3881         if (!pinfo)
3882                 return TRUE;
3883         for (i = 0; i < mono_array_length (pinfo); ++i) {
3884                 MonoReflectionParamBuilder *pb;
3885                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3886                 if (!pb)
3887                         continue;
3888                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3889                         return FALSE;
3890         }
3891
3892         return TRUE;
3893 }
3894
3895 static gboolean
3896 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3897         int i;
3898
3899         mono_error_init (error);
3900         
3901         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3902                 return FALSE;
3903         if (tb->fields) {
3904                 for (i = 0; i < tb->num_fields; ++i) {
3905                         MonoReflectionFieldBuilder* fb;
3906                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3907                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3908                                 return FALSE;
3909                 }
3910         }
3911         if (tb->events) {
3912                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3913                         MonoReflectionEventBuilder* eb;
3914                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3915                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3916                                 return FALSE;
3917                 }
3918         }
3919         if (tb->properties) {
3920                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3921                         MonoReflectionPropertyBuilder* pb;
3922                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3923                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3924                                 return FALSE;
3925                 }
3926         }
3927         if (tb->ctors) {
3928                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3929                         MonoReflectionCtorBuilder* cb;
3930                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3931                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3932                             !params_add_cattrs (assembly, cb->pinfo, error))
3933                                 return FALSE;
3934                 }
3935         }
3936
3937         if (tb->methods) {
3938                 for (i = 0; i < tb->num_methods; ++i) {
3939                         MonoReflectionMethodBuilder* mb;
3940                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3941                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3942                             !params_add_cattrs (assembly, mb->pinfo, error))
3943                                 return FALSE;
3944                 }
3945         }
3946
3947         if (tb->subtypes) {
3948                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3949                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3950                                 return FALSE;
3951                 }
3952         }
3953
3954         return TRUE;
3955 }
3956
3957 static gboolean
3958 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3959 {
3960         int i;
3961         
3962         mono_error_init (error);
3963
3964         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3965                 return FALSE;
3966
3967         if (moduleb->global_methods) {
3968                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3969                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3970                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3971                             !params_add_cattrs (assembly, mb->pinfo, error))
3972                                 return FALSE;
3973                 }
3974         }
3975
3976         if (moduleb->global_fields) {
3977                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3978                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3979                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3980                                 return FALSE;
3981                 }
3982         }
3983         
3984         if (moduleb->types) {
3985                 for (i = 0; i < moduleb->num_types; ++i) {
3986                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
3987                                 return FALSE;
3988                 }
3989         }
3990
3991         return TRUE;
3992 }
3993
3994 static void
3995 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3996 {
3997         MonoDynamicTable *table;
3998         guint32 *values;
3999         char blob_size [6];
4000         guchar hash [20];
4001         char *b = blob_size;
4002         char *dir, *path;
4003
4004         table = &assembly->tables [MONO_TABLE_FILE];
4005         table->rows++;
4006         alloc_table (table, table->rows);
4007         values = table->values + table->next_idx * MONO_FILE_SIZE;
4008         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4009         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4010         if (image_is_dynamic (module->image)) {
4011                 /* This depends on the fact that the main module is emitted last */
4012                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4013                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4014         } else {
4015                 dir = NULL;
4016                 path = g_strdup (module->image->name);
4017         }
4018         mono_sha1_get_digest_from_file (path, hash);
4019         g_free (dir);
4020         g_free (path);
4021         mono_metadata_encode_value (20, b, &b);
4022         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4023         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4024         table->next_idx ++;
4025 }
4026
4027 static void
4028 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4029 {
4030         MonoDynamicTable *table;
4031         int i;
4032
4033         table = &assembly->tables [MONO_TABLE_MODULE];
4034         mb->table_idx = table->next_idx ++;
4035         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4036         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4037         i /= 16;
4038         ++i;
4039         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4040         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4041         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4042         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4043 }
4044
4045 static guint32
4046 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4047         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4048 {
4049         MonoDynamicTable *table;
4050         guint32 *values;
4051         guint32 visib, res;
4052
4053         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4054         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4055                 return 0;
4056
4057         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4058         table->rows++;
4059         alloc_table (table, table->rows);
4060         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4061
4062         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4063         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4064         if (klass->nested_in)
4065                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4066         else
4067                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4068         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4069         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4070
4071         res = table->next_idx;
4072
4073         table->next_idx ++;
4074
4075         /* Emit nested types */
4076         if (klass->ext && klass->ext->nested_classes) {
4077                 GList *tmp;
4078
4079                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4080                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4081         }
4082
4083         return res;
4084 }
4085
4086 static void
4087 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4088         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4089 {
4090         MonoClass *klass;
4091         guint32 idx, i;
4092
4093         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4094
4095         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4096
4097         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4098                                                                                                    parent_index, assembly);
4099
4100         /* 
4101          * Emit nested types
4102          * We need to do this ourselves since klass->nested_classes is not set up.
4103          */
4104         if (tb->subtypes) {
4105                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4106                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4107         }
4108 }
4109
4110 static void
4111 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4112         guint32 module_index, MonoDynamicImage *assembly)
4113 {
4114         MonoImage *image = module->image;
4115         MonoTableInfo  *t;
4116         guint32 i;
4117
4118         t = &image->tables [MONO_TABLE_TYPEDEF];
4119
4120         for (i = 0; i < t->rows; ++i) {
4121                 MonoError error;
4122                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4123                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4124
4125                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4126                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4127         }
4128 }
4129
4130 static void
4131 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4132 {
4133         MonoDynamicTable *table;
4134         guint32 *values;
4135         guint32 scope, scope_idx, impl, current_idx;
4136         gboolean forwarder = TRUE;
4137         gpointer iter = NULL;
4138         MonoClass *nested;
4139
4140         if (klass->nested_in) {
4141                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4142                 forwarder = FALSE;
4143         } else {
4144                 scope = resolution_scope_from_image (assembly, klass->image);
4145                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4146                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4147                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4148         }
4149
4150         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4151
4152         table->rows++;
4153         alloc_table (table, table->rows);
4154         current_idx = table->next_idx;
4155         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4156
4157         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4158         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4159         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4160         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4161         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4162
4163         table->next_idx++;
4164
4165         while ((nested = mono_class_get_nested_types (klass, &iter)))
4166                 add_exported_type (assemblyb, assembly, nested, current_idx);
4167 }
4168
4169 static void
4170 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4171 {
4172         MonoClass *klass;
4173         int i;
4174
4175         if (!assemblyb->type_forwarders)
4176                 return;
4177
4178         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4179                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4180                 MonoType *type;
4181                 if (!t)
4182                         continue;
4183
4184                 type = mono_reflection_type_get_handle (t);
4185                 g_assert (type);
4186
4187                 klass = mono_class_from_mono_type (type);
4188
4189                 add_exported_type (assemblyb, assembly, klass, 0);
4190         }
4191 }
4192
4193 #define align_pointer(base,p)\
4194         do {\
4195                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4196                 if (__diff & 3)\
4197                         (p) += 4 - (__diff & 3);\
4198         } while (0)
4199
4200 static int
4201 compare_constants (const void *a, const void *b)
4202 {
4203         const guint32 *a_values = (const guint32 *)a;
4204         const guint32 *b_values = (const guint32 *)b;
4205         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4206 }
4207
4208 static int
4209 compare_semantics (const void *a, const void *b)
4210 {
4211         const guint32 *a_values = (const guint32 *)a;
4212         const guint32 *b_values = (const guint32 *)b;
4213         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4214         if (assoc)
4215                 return assoc;
4216         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4217 }
4218
4219 static int
4220 compare_custom_attrs (const void *a, const void *b)
4221 {
4222         const guint32 *a_values = (const guint32 *)a;
4223         const guint32 *b_values = (const guint32 *)b;
4224
4225         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4226 }
4227
4228 static int
4229 compare_field_marshal (const void *a, const void *b)
4230 {
4231         const guint32 *a_values = (const guint32 *)a;
4232         const guint32 *b_values = (const guint32 *)b;
4233
4234         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4235 }
4236
4237 static int
4238 compare_nested (const void *a, const void *b)
4239 {
4240         const guint32 *a_values = (const guint32 *)a;
4241         const guint32 *b_values = (const guint32 *)b;
4242
4243         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4244 }
4245
4246 static int
4247 compare_genericparam (const void *a, const void *b)
4248 {
4249         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4250         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4251
4252         if ((*b_entry)->owner == (*a_entry)->owner)
4253                 return 
4254                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4255                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4256         else
4257                 return (*a_entry)->owner - (*b_entry)->owner;
4258 }
4259
4260 static int
4261 compare_declsecurity_attrs (const void *a, const void *b)
4262 {
4263         const guint32 *a_values = (const guint32 *)a;
4264         const guint32 *b_values = (const guint32 *)b;
4265
4266         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4267 }
4268
4269 static int
4270 compare_interface_impl (const void *a, const void *b)
4271 {
4272         const guint32 *a_values = (const guint32 *)a;
4273         const guint32 *b_values = (const guint32 *)b;
4274
4275         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4276         if (klass)
4277                 return klass;
4278
4279         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4280 }
4281
4282 static void
4283 pad_heap (MonoDynamicStream *sh)
4284 {
4285         if (sh->index & 3) {
4286                 int sz = 4 - (sh->index & 3);
4287                 memset (sh->data + sh->index, 0, sz);
4288                 sh->index += sz;
4289         }
4290 }
4291
4292 struct StreamDesc {
4293         const char *name;
4294         MonoDynamicStream *stream;
4295 };
4296
4297 /*
4298  * build_compressed_metadata() fills in the blob of data that represents the 
4299  * raw metadata as it will be saved in the PE file. The five streams are output 
4300  * and the metadata tables are comnpressed from the guint32 array representation, 
4301  * to the compressed on-disk format.
4302  */
4303 static void
4304 build_compressed_metadata (MonoDynamicImage *assembly)
4305 {
4306         MonoDynamicTable *table;
4307         int i;
4308         guint64 valid_mask = 0;
4309         guint64 sorted_mask;
4310         guint32 heapt_size = 0;
4311         guint32 meta_size = 256; /* allow for header and other stuff */
4312         guint32 table_offset;
4313         guint32 ntables = 0;
4314         guint64 *int64val;
4315         guint32 *int32val;
4316         guint16 *int16val;
4317         MonoImage *meta;
4318         unsigned char *p;
4319         struct StreamDesc stream_desc [5];
4320
4321         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4322         for (i = 0; i < assembly->gen_params->len; i++){
4323                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4324                 write_generic_param_entry (assembly, entry);
4325         }
4326
4327         stream_desc [0].name  = "#~";
4328         stream_desc [0].stream = &assembly->tstream;
4329         stream_desc [1].name  = "#Strings";
4330         stream_desc [1].stream = &assembly->sheap;
4331         stream_desc [2].name  = "#US";
4332         stream_desc [2].stream = &assembly->us;
4333         stream_desc [3].name  = "#Blob";
4334         stream_desc [3].stream = &assembly->blob;
4335         stream_desc [4].name  = "#GUID";
4336         stream_desc [4].stream = &assembly->guid;
4337         
4338         /* tables that are sorted */
4339         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4340                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4341                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4342                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4343                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4344                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4345                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4346         
4347         /* Compute table sizes */
4348         /* the MonoImage has already been created in mono_image_basic_init() */
4349         meta = &assembly->image;
4350
4351         /* sizes should be multiple of 4 */
4352         pad_heap (&assembly->blob);
4353         pad_heap (&assembly->guid);
4354         pad_heap (&assembly->sheap);
4355         pad_heap (&assembly->us);
4356
4357         /* Setup the info used by compute_sizes () */
4358         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4359         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4360         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4361
4362         meta_size += assembly->blob.index;
4363         meta_size += assembly->guid.index;
4364         meta_size += assembly->sheap.index;
4365         meta_size += assembly->us.index;
4366
4367         for (i=0; i < MONO_TABLE_NUM; ++i)
4368                 meta->tables [i].rows = assembly->tables [i].rows;
4369         
4370         for (i = 0; i < MONO_TABLE_NUM; i++){
4371                 if (meta->tables [i].rows == 0)
4372                         continue;
4373                 valid_mask |= (guint64)1 << i;
4374                 ntables ++;
4375                 meta->tables [i].row_size = mono_metadata_compute_size (
4376                         meta, i, &meta->tables [i].size_bitfield);
4377                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4378         }
4379         heapt_size += 24; /* #~ header size */
4380         heapt_size += ntables * 4;
4381         /* make multiple of 4 */
4382         heapt_size += 3;
4383         heapt_size &= ~3;
4384         meta_size += heapt_size;
4385         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4386         p = (unsigned char*)meta->raw_metadata;
4387         /* the metadata signature */
4388         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4389         /* version numbers and 4 bytes reserved */
4390         int16val = (guint16*)p;
4391         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4392         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4393         p += 8;
4394         /* version string */
4395         int32val = (guint32*)p;
4396         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4397         p += 4;
4398         memcpy (p, meta->version, strlen (meta->version));
4399         p += GUINT32_FROM_LE (*int32val);
4400         align_pointer (meta->raw_metadata, p);
4401         int16val = (guint16*)p;
4402         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4403         *int16val = GUINT16_TO_LE (5); /* number of streams */
4404         p += 4;
4405
4406         /*
4407          * write the stream info.
4408          */
4409         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4410         table_offset += 3; table_offset &= ~3;
4411
4412         assembly->tstream.index = heapt_size;
4413         for (i = 0; i < 5; ++i) {
4414                 int32val = (guint32*)p;
4415                 stream_desc [i].stream->offset = table_offset;
4416                 *int32val++ = GUINT32_TO_LE (table_offset);
4417                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4418                 table_offset += GUINT32_FROM_LE (*int32val);
4419                 table_offset += 3; table_offset &= ~3;
4420                 p += 8;
4421                 strcpy ((char*)p, stream_desc [i].name);
4422                 p += strlen (stream_desc [i].name) + 1;
4423                 align_pointer (meta->raw_metadata, p);
4424         }
4425         /* 
4426          * now copy the data, the table stream header and contents goes first.
4427          */
4428         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4429         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4430         int32val = (guint32*)p;
4431         *int32val = GUINT32_TO_LE (0); /* reserved */
4432         p += 4;
4433
4434         *p++ = 2; /* version */
4435         *p++ = 0;
4436
4437         if (meta->idx_string_wide)
4438                 *p |= 0x01;
4439         if (meta->idx_guid_wide)
4440                 *p |= 0x02;
4441         if (meta->idx_blob_wide)
4442                 *p |= 0x04;
4443         ++p;
4444         *p++ = 1; /* reserved */
4445         int64val = (guint64*)p;
4446         *int64val++ = GUINT64_TO_LE (valid_mask);
4447         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4448         p += 16;
4449         int32val = (guint32*)p;
4450         for (i = 0; i < MONO_TABLE_NUM; i++){
4451                 if (meta->tables [i].rows == 0)
4452                         continue;
4453                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4454         }
4455         p = (unsigned char*)int32val;
4456
4457         /* sort the tables that still need sorting */
4458         table = &assembly->tables [MONO_TABLE_CONSTANT];
4459         if (table->rows)
4460                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4461         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4462         if (table->rows)
4463                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4464         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4465         if (table->rows)
4466                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4467         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4468         if (table->rows)
4469                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4470         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4471         if (table->rows)
4472                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4473         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4474         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4475         if (table->rows)
4476                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4477         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4478         if (table->rows)
4479                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4480
4481         /* compress the tables */
4482         for (i = 0; i < MONO_TABLE_NUM; i++){
4483                 int row, col;
4484                 guint32 *values;
4485                 guint32 bitfield = meta->tables [i].size_bitfield;
4486                 if (!meta->tables [i].rows)
4487                         continue;
4488                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4489                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4490                 meta->tables [i].base = (char*)p;
4491                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4492                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4493                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4494                                 switch (mono_metadata_table_size (bitfield, col)) {
4495                                 case 1:
4496                                         *p++ = values [col];
4497                                         break;
4498                                 case 2:
4499                                         *p++ = values [col] & 0xff;
4500                                         *p++ = (values [col] >> 8) & 0xff;
4501                                         break;
4502                                 case 4:
4503                                         *p++ = values [col] & 0xff;
4504                                         *p++ = (values [col] >> 8) & 0xff;
4505                                         *p++ = (values [col] >> 16) & 0xff;
4506                                         *p++ = (values [col] >> 24) & 0xff;
4507                                         break;
4508                                 default:
4509                                         g_assert_not_reached ();
4510                                 }
4511                         }
4512                 }
4513                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4514         }
4515         
4516         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4517         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4518         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4519         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4520         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4521
4522         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4523 }
4524
4525 /*
4526  * Some tables in metadata need to be sorted according to some criteria, but
4527  * when methods and fields are first created with reflection, they may be assigned a token
4528  * that doesn't correspond to the final token they will get assigned after the sorting.
4529  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4530  * with the reflection objects that represent them. Once all the tables are set up, the 
4531  * reflection objects will contains the correct table index. fixup_method() will fixup the
4532  * tokens for the method with ILGenerator @ilgen.
4533  */
4534 static void
4535 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4536 {
4537         guint32 code_idx = GPOINTER_TO_UINT (value);
4538         MonoReflectionILTokenInfo *iltoken;
4539         MonoReflectionFieldBuilder *field;
4540         MonoReflectionCtorBuilder *ctor;
4541         MonoReflectionMethodBuilder *method;
4542         MonoReflectionTypeBuilder *tb;
4543         MonoReflectionArrayMethod *am;
4544         guint32 i, idx = 0;
4545         unsigned char *target;
4546
4547         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4548                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4549                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4550                 switch (target [3]) {
4551                 case MONO_TABLE_FIELD:
4552                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4553                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4554                                 idx = field->table_idx;
4555                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4556                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4557                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4558                         } else {
4559                                 g_assert_not_reached ();
4560                         }
4561                         break;
4562                 case MONO_TABLE_METHOD:
4563                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4564                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4565                                 idx = method->table_idx;
4566                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4567                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4568                                 idx = ctor->table_idx;
4569                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4570                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4571                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4572                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4573                         } else {
4574                                 g_assert_not_reached ();
4575                         }
4576                         break;
4577                 case MONO_TABLE_TYPEDEF:
4578                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4579                                 g_assert_not_reached ();
4580                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4581                         idx = tb->table_idx;
4582                         break;
4583                 case MONO_TABLE_MEMBERREF:
4584                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4585                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4586                                 idx = am->table_idx;
4587                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4588                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4589                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4590                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4591                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4592                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4593                                 continue;
4594                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4595                                 continue;
4596                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4597                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4598                                 g_assert (is_field_on_inst (f));
4599                                 continue;
4600                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4601                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4602                                 continue;
4603                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4604                                 continue;
4605                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4606                                 continue;
4607                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4608                                 continue;
4609                         } else {
4610                                 g_assert_not_reached ();
4611                         }
4612                         break;
4613                 case MONO_TABLE_METHODSPEC:
4614                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4615                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616                                 g_assert (mono_method_signature (m)->generic_param_count);
4617                                 continue;
4618                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4619                                 continue;
4620                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4621                                 continue;
4622                         } else {
4623                                 g_assert_not_reached ();
4624                         }
4625                         break;
4626                 default:
4627                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4628                 }
4629                 target [0] = idx & 0xff;
4630                 target [1] = (idx >> 8) & 0xff;
4631                 target [2] = (idx >> 16) & 0xff;
4632         }
4633 }
4634
4635 /*
4636  * fixup_cattrs:
4637  *
4638  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4639  * value is not known when the table is emitted.
4640  */
4641 static void
4642 fixup_cattrs (MonoDynamicImage *assembly)
4643 {
4644         MonoDynamicTable *table;
4645         guint32 *values;
4646         guint32 type, i, idx, token;
4647         MonoObject *ctor;
4648
4649         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4650
4651         for (i = 0; i < table->rows; ++i) {
4652                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4653
4654                 type = values [MONO_CUSTOM_ATTR_TYPE];
4655                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4656                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4657                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4658                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4659                         g_assert (ctor);
4660
4661                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4662                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4663                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4664                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4665                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4666                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4667                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4668                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4669                         }
4670                 }
4671         }
4672 }
4673
4674 static void
4675 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4676 {
4677         MonoDynamicTable *table;
4678         guint32 *values;
4679
4680         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4681         table->rows++;
4682         alloc_table (table, table->rows);
4683         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4684         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4685         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4686         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4687         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4688         table->next_idx++;
4689 }
4690
4691 static void
4692 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4693 {
4694         MonoDynamicTable *table;
4695         guint32 *values;
4696         char blob_size [6];
4697         guchar hash [20];
4698         char *b = blob_size;
4699         char *name, *sname;
4700         guint32 idx, offset;
4701
4702         if (rsrc->filename) {
4703                 name = mono_string_to_utf8 (rsrc->filename);
4704                 sname = g_path_get_basename (name);
4705         
4706                 table = &assembly->tables [MONO_TABLE_FILE];
4707                 table->rows++;
4708                 alloc_table (table, table->rows);
4709                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4710                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4711                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4712                 g_free (sname);
4713
4714                 mono_sha1_get_digest_from_file (name, hash);
4715                 mono_metadata_encode_value (20, b, &b);
4716                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4717                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4718                 g_free (name);
4719                 idx = table->next_idx++;
4720                 rsrc->offset = 0;
4721                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4722         } else {
4723                 char sizebuf [4];
4724                 char *data;
4725                 guint len;
4726                 if (rsrc->data) {
4727                         data = mono_array_addr (rsrc->data, char, 0);
4728                         len = mono_array_length (rsrc->data);
4729                 } else {
4730                         data = NULL;
4731                         len = 0;
4732                 }
4733                 offset = len;
4734                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4735                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4736                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4737                 mono_image_add_stream_data (&assembly->resources, data, len);
4738
4739                 if (!mb->is_main)
4740                         /* 
4741                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4742                          * the main module, but that needs to reference the FILE table
4743                          * which isn't emitted yet.
4744                          */
4745                         return;
4746                 else
4747                         idx = 0;
4748         }
4749
4750         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4751 }
4752
4753 static void
4754 set_version_from_string (MonoString *version, guint32 *values)
4755 {
4756         gchar *ver, *p, *str;
4757         guint32 i;
4758         
4759         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4760         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4761         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4762         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4763         if (!version)
4764                 return;
4765         ver = str = mono_string_to_utf8 (version);
4766         for (i = 0; i < 4; ++i) {
4767                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4768                 switch (*p) {
4769                 case '.':
4770                         p++;
4771                         break;
4772                 case '*':
4773                         /* handle Revision and Build */
4774                         p++;
4775                         break;
4776                 }
4777                 ver = p;
4778         }
4779         g_free (str);
4780 }
4781
4782 static guint32
4783 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4784         gsize len;
4785         guint32 token = 0;
4786         char blob_size [6];
4787         char *b = blob_size;
4788
4789         if (!pkey)
4790                 return token;
4791
4792         len = mono_array_length (pkey);
4793         mono_metadata_encode_value (len, b, &b);
4794         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4795         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4796
4797         assembly->public_key = (guint8 *)g_malloc (len);
4798         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4799         assembly->public_key_len = len;
4800
4801         /* Special case: check for ECMA key (16 bytes) */
4802         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4803                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4804                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4805         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4806                 /* minimum key size (in 2.0) is 384 bits */
4807                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4808         } else {
4809                 /* FIXME - verifier */
4810                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4811                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4812         }
4813         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4814
4815         return token;
4816 }
4817
4818 static void
4819 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4820 {
4821         MonoDynamicTable *table;
4822         MonoDynamicImage *assembly;
4823         MonoReflectionAssemblyBuilder *assemblyb;
4824         MonoDomain *domain;
4825         guint32 *values;
4826         int i;
4827         guint32 module_index;
4828
4829         assemblyb = moduleb->assemblyb;
4830         assembly = moduleb->dynamic_image;
4831         domain = mono_object_domain (assemblyb);
4832
4833         /* Emit ASSEMBLY table */
4834         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4835         alloc_table (table, 1);
4836         values = table->values + MONO_ASSEMBLY_SIZE;
4837         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4838         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4839         if (assemblyb->culture) {
4840                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4841         } else {
4842                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4843         }
4844         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4845         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4846         set_version_from_string (assemblyb->version, values);
4847
4848         /* Emit FILE + EXPORTED_TYPE table */
4849         module_index = 0;
4850         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4851                 int j;
4852                 MonoReflectionModuleBuilder *file_module = 
4853                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4854                 if (file_module != moduleb) {
4855                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4856                         module_index ++;
4857                         if (file_module->types) {
4858                                 for (j = 0; j < file_module->num_types; ++j) {
4859                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4860                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4861                                 }
4862                         }
4863                 }
4864         }
4865         if (assemblyb->loaded_modules) {
4866                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4867                         MonoReflectionModule *file_module = 
4868                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4869                         mono_image_fill_file_table (domain, file_module, assembly);
4870                         module_index ++;
4871                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4872                 }
4873         }
4874         if (assemblyb->type_forwarders)
4875                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4876
4877         /* Emit MANIFESTRESOURCE table */
4878         module_index = 0;
4879         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4880                 int j;
4881                 MonoReflectionModuleBuilder *file_module = 
4882                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4883                 /* The table for the main module is emitted later */
4884                 if (file_module != moduleb) {
4885                         module_index ++;
4886                         if (file_module->resources) {
4887                                 int len = mono_array_length (file_module->resources);
4888                                 for (j = 0; j < len; ++j) {
4889                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4890                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4891                                 }
4892                         }
4893                 }
4894         }               
4895 }
4896
4897 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4898
4899 /*
4900  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4901  * for the modulebuilder @moduleb.
4902  * At the end of the process, method and field tokens are fixed up and the 
4903  * on-disk compressed metadata representation is created.
4904  * Return TRUE on success, or FALSE on failure and sets @error
4905  */
4906 gboolean
4907 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4908 {
4909         MonoDynamicTable *table;
4910         MonoDynamicImage *assembly;
4911         MonoReflectionAssemblyBuilder *assemblyb;
4912         MonoDomain *domain;
4913         MonoPtrArray types;
4914         guint32 *values;
4915         int i, j;
4916
4917         mono_error_init (error);
4918
4919         assemblyb = moduleb->assemblyb;
4920         assembly = moduleb->dynamic_image;
4921         domain = mono_object_domain (assemblyb);
4922
4923         if (assembly->text_rva)
4924                 return TRUE;
4925
4926         assembly->text_rva = START_TEXT_RVA;
4927
4928         if (moduleb->is_main) {
4929                 mono_image_emit_manifest (moduleb);
4930         }
4931
4932         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4933         table->rows = 1; /* .<Module> */
4934         table->next_idx++;
4935         alloc_table (table, table->rows);
4936         /*
4937          * Set the first entry.
4938          */
4939         values = table->values + table->columns;
4940         values [MONO_TYPEDEF_FLAGS] = 0;
4941         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4942         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4943         values [MONO_TYPEDEF_EXTENDS] = 0;
4944         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4945         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4946
4947         /* 
4948          * handle global methods 
4949          * FIXME: test what to do when global methods are defined in multiple modules.
4950          */
4951         if (moduleb->global_methods) {
4952                 table = &assembly->tables [MONO_TABLE_METHOD];
4953                 table->rows += mono_array_length (moduleb->global_methods);
4954                 alloc_table (table, table->rows);
4955                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4956                         mono_image_get_method_info (
4957                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4958         }
4959         if (moduleb->global_fields) {
4960                 table = &assembly->tables [MONO_TABLE_FIELD];
4961                 table->rows += mono_array_length (moduleb->global_fields);
4962                 alloc_table (table, table->rows);
4963                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4964                         mono_image_get_field_info (
4965                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4966         }
4967
4968         table = &assembly->tables [MONO_TABLE_MODULE];
4969         alloc_table (table, 1);
4970         mono_image_fill_module_table (domain, moduleb, assembly);
4971
4972         /* Collect all types into a list sorted by their table_idx */
4973         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4974
4975         if (moduleb->types)
4976                 for (i = 0; i < moduleb->num_types; ++i) {
4977                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4978                         collect_types (&types, type);
4979                 }
4980
4981         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4982         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4983         table->rows += mono_ptr_array_size (types);
4984         alloc_table (table, table->rows);
4985
4986         /*
4987          * Emit type names + namespaces at one place inside the string heap,
4988          * so load_class_names () needs to touch fewer pages.
4989          */
4990         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4991                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4992                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4993         }
4994         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4995                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4996                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4997         }
4998
4999         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5000                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5001                 mono_image_get_type_info (domain, type, assembly);
5002         }
5003
5004         /* 
5005          * table->rows is already set above and in mono_image_fill_module_table.
5006          */
5007         /* add all the custom attributes at the end, once all the indexes are stable */
5008         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5009                 goto leave_types;
5010
5011         /* CAS assembly permissions */
5012         if (assemblyb->permissions_minimum)
5013                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5014         if (assemblyb->permissions_optional)
5015                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5016         if (assemblyb->permissions_refused)
5017                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5018
5019         if (!module_add_cattrs (assembly, moduleb, error))
5020                 goto leave_types;
5021
5022         /* fixup tokens */
5023         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5024
5025         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5026          * the final tokens and don't need another fixup pass. */
5027
5028         if (moduleb->global_methods) {
5029                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5030                         MonoReflectionMethodBuilder *mb = mono_array_get (
5031                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5032                         if (!mono_image_add_methodimpl (assembly, mb, error))
5033                                 goto leave_types;
5034                 }
5035         }
5036
5037         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5038                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5039                 if (type->methods) {
5040                         for (j = 0; j < type->num_methods; ++j) {
5041                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5042                                         type->methods, MonoReflectionMethodBuilder*, j);
5043
5044                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5045                                         goto leave_types;
5046                         }
5047                 }
5048         }
5049
5050         fixup_cattrs (assembly);
5051
5052 leave_types:
5053         mono_ptr_array_destroy (types);
5054 leave:
5055
5056         return mono_error_ok (error);
5057 }
5058
5059 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5060
5061 gboolean
5062 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5063 {
5064         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5065 }
5066
5067 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5068
5069
5070 typedef struct {
5071         guint32 import_lookup_table;
5072         guint32 timestamp;
5073         guint32 forwarder;
5074         guint32 name_rva;
5075         guint32 import_address_table_rva;
5076 } MonoIDT;
5077
5078 typedef struct {
5079         guint32 name_rva;
5080         guint32 flags;
5081 } MonoILT;
5082
5083 #ifndef DISABLE_REFLECTION_EMIT
5084
5085 /*
5086  * mono_image_insert_string:
5087  * @module: module builder object
5088  * @str: a string
5089  *
5090  * Insert @str into the user string stream of @module.
5091  */
5092 guint32
5093 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5094 {
5095         MonoDynamicImage *assembly;
5096         guint32 idx;
5097         char buf [16];
5098         char *b = buf;
5099         
5100         if (!module->dynamic_image)
5101                 mono_image_module_basic_init (module);
5102
5103         assembly = module->dynamic_image;
5104         
5105         if (assembly->save) {
5106                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5107                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5108 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5109         {
5110                 char *swapped = g_malloc (2 * mono_string_length (str));
5111                 const char *p = (const char*)mono_string_chars (str);
5112
5113                 swap_with_size (swapped, p, 2, mono_string_length (str));
5114                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5115                 g_free (swapped);
5116         }
5117 #else
5118                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5119 #endif
5120                 mono_image_add_stream_data (&assembly->us, "", 1);
5121         } else {
5122                 idx = assembly->us.index ++;
5123         }
5124
5125         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5126
5127         return MONO_TOKEN_STRING | idx;
5128 }
5129
5130 guint32
5131 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5132 {
5133         MonoClass *klass;
5134         guint32 token = 0;
5135         MonoMethodSignature *sig;
5136
5137         mono_error_init (error);
5138
5139         klass = obj->vtable->klass;
5140         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5141                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5142                 MonoMethodSignature *old;
5143                 guint32 sig_token, parent;
5144                 int nargs, i;
5145
5146                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5147
5148                 nargs = mono_array_length (opt_param_types);
5149                 old = mono_method_signature (method);
5150                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5151
5152                 sig->hasthis = old->hasthis;
5153                 sig->explicit_this = old->explicit_this;
5154                 sig->call_convention = old->call_convention;
5155                 sig->generic_param_count = old->generic_param_count;
5156                 sig->param_count = old->param_count + nargs;
5157                 sig->sentinelpos = old->param_count;
5158                 sig->ret = old->ret;
5159
5160                 for (i = 0; i < old->param_count; i++)
5161                         sig->params [i] = old->params [i];
5162
5163                 for (i = 0; i < nargs; i++) {
5164                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5165                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5166                 }
5167
5168                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5169                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5170                 parent >>= MONO_TYPEDEFORREF_BITS;
5171
5172                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5173                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5174
5175                 sig_token = method_encode_signature (assembly, sig);
5176                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5177         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5178                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5179                 ReflectionMethodBuilder rmb;
5180                 guint32 parent, sig_token;
5181                 int nopt_args, nparams, ngparams, i;
5182
5183                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5184                         goto fail;
5185                 
5186                 rmb.opt_types = opt_param_types;
5187                 nopt_args = mono_array_length (opt_param_types);
5188
5189                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5190                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5191                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5192
5193                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5194                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5195                 sig->call_convention = rmb.call_conv;
5196                 sig->generic_param_count = ngparams;
5197                 sig->param_count = nparams + nopt_args;
5198                 sig->sentinelpos = nparams;
5199                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5200
5201                 for (i = 0; i < nparams; i++) {
5202                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5203                         sig->params [i] = mono_reflection_type_get_handle (rt);
5204                 }
5205
5206                 for (i = 0; i < nopt_args; i++) {
5207                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5208                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5209                 }
5210
5211                 sig_token = method_builder_encode_signature (assembly, &rmb);
5212
5213                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5214                 if (!mono_error_ok (error))
5215                         goto fail;
5216                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5217
5218                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5219                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5220
5221                 char *name = mono_string_to_utf8 (rmb.name);
5222                 token = mono_image_get_varargs_method_token (
5223                         assembly, parent, name, sig_token);
5224                 g_free (name);
5225         } else {
5226                 g_error ("requested method token for %s\n", klass->name);
5227         }
5228
5229         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5230         register_dyn_token (assembly, token, obj);
5231         return token;
5232 fail:
5233         g_assert (!mono_error_ok (error));
5234         return 0;
5235 }
5236
5237 /*
5238  * mono_image_create_token:
5239  * @assembly: a dynamic assembly
5240  * @obj:
5241  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5242  *
5243  * Get a token to insert in the IL code stream for the given MemberInfo.
5244  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5245  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5246  * entry.
5247  */
5248 guint32
5249 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5250                          gboolean create_open_instance, gboolean register_token,
5251                          MonoError *error)
5252 {
5253         MonoClass *klass;
5254         guint32 token = 0;
5255
5256         mono_error_init (error);
5257
5258         klass = obj->vtable->klass;
5259
5260         /* Check for user defined reflection objects */
5261         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5262         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5263                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5264                 return 0;
5265         }
5266
5267         if (strcmp (klass->name, "MethodBuilder") == 0) {
5268                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5269                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5270
5271                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5272                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5273                 else
5274                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5275                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5276         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5277                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5278                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5279
5280                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5281                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5282                 else
5283                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5284                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5285         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5286                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5287                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5288                 if (tb->generic_params) {
5289                         token = mono_image_get_generic_field_token (assembly, fb);
5290                 } else {
5291                         if (tb->module->dynamic_image == assembly) {
5292                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5293                         } else {
5294                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5295                         }
5296                 }
5297         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5298                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5299                 if (create_open_instance && tb->generic_params) {
5300                         MonoType *type;
5301                         init_type_builder_generics (obj);
5302                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5303                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5304                         token = mono_metadata_token_from_dor (token);
5305                 } else if (tb->module->dynamic_image == assembly) {
5306                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5307                 } else {
5308                         MonoType *type;
5309                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5310                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5311                 }
5312         } else if (strcmp (klass->name, "MonoType") == 0) {
5313                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5314                 MonoClass *mc = mono_class_from_mono_type (type);
5315                 token = mono_metadata_token_from_dor (
5316                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5317         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5318                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5319                 token = mono_metadata_token_from_dor (
5320                         mono_image_typedef_or_ref (assembly, type));
5321         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5322                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5323                 token = mono_metadata_token_from_dor (
5324                         mono_image_typedef_or_ref (assembly, type));
5325         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5326                    strcmp (klass->name, "MonoMethod") == 0 ||
5327                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5328                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5329                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5330                 if (m->method->is_inflated) {
5331                         if (create_open_instance)
5332                                 token = mono_image_get_methodspec_token (assembly, m->method);
5333                         else
5334                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5335                 } else if ((m->method->klass->image == &assembly->image) &&
5336                          !m->method->klass->generic_class) {
5337                         static guint32 method_table_idx = 0xffffff;
5338                         if (m->method->klass->wastypebuilder) {
5339                                 /* we use the same token as the one that was assigned
5340                                  * to the Methodbuilder.
5341                                  * FIXME: do the equivalent for Fields.
5342                                  */
5343                                 token = m->method->token;
5344                         } else {
5345                                 /*
5346                                  * Each token should have a unique index, but the indexes are
5347                                  * assigned by managed code, so we don't know about them. An
5348                                  * easy solution is to count backwards...
5349                                  */
5350                                 method_table_idx --;
5351                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5352                         }
5353                 } else {
5354                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5355                 }
5356                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5357         } else if (strcmp (klass->name, "MonoField") == 0) {
5358                 MonoReflectionField *f = (MonoReflectionField *)obj;
5359                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5360                         static guint32 field_table_idx = 0xffffff;
5361                         field_table_idx --;
5362                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5363                 } else {
5364                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5365                 }
5366                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5367         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5368                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5369                 token = mono_image_get_array_token (assembly, m);
5370         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5371                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5372                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5373         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5374                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5375                 token = mono_metadata_token_from_dor (
5376                         mono_image_typedef_or_ref (assembly, type));
5377         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5378                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5379                 token = mono_image_get_field_on_inst_token (assembly, f);
5380         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5381                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5382                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5383         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5384                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5385                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5386         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5387                 MonoReflectionType *type = (MonoReflectionType *)obj;
5388                 token = mono_metadata_token_from_dor (
5389                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5390         } else {
5391                 g_error ("requested token for %s\n", klass->name);
5392         }
5393
5394         if (register_token)
5395                 mono_image_register_token (assembly, token, obj);
5396
5397         return token;
5398 }
5399
5400 /*
5401  * mono_image_register_token:
5402  *
5403  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5404  * the Module.ResolveXXXToken () methods to work.
5405  */
5406 void
5407 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5408 {
5409         MonoObject *prev;
5410
5411         dynamic_image_lock (assembly);
5412         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5413         if (prev) {
5414                 /* There could be multiple MethodInfo objects with the same token */
5415                 //g_assert (prev == obj);
5416         } else {
5417                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5418         }
5419         dynamic_image_unlock (assembly);
5420 }
5421
5422 static MonoDynamicImage*
5423 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5424 {
5425         static const guchar entrycode [16] = {0xff, 0x25, 0};
5426         MonoDynamicImage *image;
5427         int i;
5428
5429         const char *version;
5430
5431         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5432                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5433         else
5434                 version = mono_get_runtime_info ()->runtime_version;
5435
5436 #if HAVE_BOEHM_GC
5437         /* The MonoGHashTable's need GC tracking */
5438         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5439 #else
5440         image = g_new0 (MonoDynamicImage, 1);
5441 #endif
5442
5443         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5444         
5445         /*g_print ("created image %p\n", image);*/
5446         /* keep in sync with image.c */
5447         image->image.name = assembly_name;
5448         image->image.assembly_name = image->image.name; /* they may be different */
5449         image->image.module_name = module_name;
5450         image->image.version = g_strdup (version);
5451         image->image.md_version_major = 1;
5452         image->image.md_version_minor = 1;
5453         image->image.dynamic = TRUE;
5454
5455         image->image.references = g_new0 (MonoAssembly*, 1);
5456         image->image.references [0] = NULL;
5457
5458         mono_image_init (&image->image);
5459
5460         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");
5461         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5462         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5463         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5464         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5465         image->handleref = g_hash_table_new (NULL, NULL);
5466         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");
5467         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5468         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");
5469         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");
5470         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5471         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5472         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5473         image->gen_params = g_ptr_array_new ();
5474         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5475
5476         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5477         string_heap_init (&image->sheap);
5478         mono_image_add_stream_data (&image->us, "", 1);
5479         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5480         /* import tables... */
5481         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5482         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5483         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5484         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5485         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5486         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5487         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5488         stream_data_align (&image->code);
5489
5490         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5491
5492         for (i=0; i < MONO_TABLE_NUM; ++i) {
5493                 image->tables [i].next_idx = 1;
5494                 image->tables [i].columns = table_sizes [i];
5495         }
5496
5497         image->image.assembly = (MonoAssembly*)assembly;
5498         image->run = assembly->run;
5499         image->save = assembly->save;
5500         image->pe_kind = 0x1; /* ILOnly */
5501         image->machine = 0x14c; /* I386 */
5502         
5503         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5504
5505         dynamic_images_lock ();
5506
5507         if (!dynamic_images)
5508                 dynamic_images = g_ptr_array_new ();
5509
5510         g_ptr_array_add (dynamic_images, image);
5511
5512         dynamic_images_unlock ();
5513
5514         return image;
5515 }
5516 #endif
5517
5518 static void
5519 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5520 {
5521         g_free (key);
5522 }
5523
5524 static void
5525 release_hashtable (MonoGHashTable **hash)
5526 {
5527         if (*hash) {
5528                 mono_g_hash_table_destroy (*hash);
5529                 *hash = NULL;
5530         }
5531 }
5532
5533 void
5534 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5535 {
5536         release_hashtable (&image->token_fixups);
5537         release_hashtable (&image->handleref_managed);
5538         release_hashtable (&image->tokens);
5539         release_hashtable (&image->remapped_tokens);
5540         release_hashtable (&image->generic_def_objects);
5541         release_hashtable (&image->methodspec);
5542 }
5543
5544 // Free dynamic image pass one: Free resources but not image itself
5545 void
5546 mono_dynamic_image_free (MonoDynamicImage *image)
5547 {
5548         MonoDynamicImage *di = image;
5549         GList *list;
5550         int i;
5551
5552         if (di->methodspec)
5553                 mono_g_hash_table_destroy (di->methodspec);
5554         if (di->typespec)
5555                 g_hash_table_destroy (di->typespec);
5556         if (di->typeref)
5557                 g_hash_table_destroy (di->typeref);
5558         if (di->handleref)
5559                 g_hash_table_destroy (di->handleref);
5560         if (di->handleref_managed)
5561                 mono_g_hash_table_destroy (di->handleref_managed);
5562         if (di->tokens)
5563                 mono_g_hash_table_destroy (di->tokens);
5564         if (di->remapped_tokens)
5565                 mono_g_hash_table_destroy (di->remapped_tokens);
5566         if (di->generic_def_objects)
5567                 mono_g_hash_table_destroy (di->generic_def_objects);
5568         if (di->blob_cache) {
5569                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5570                 g_hash_table_destroy (di->blob_cache);
5571         }
5572         if (di->standalonesig_cache)
5573                 g_hash_table_destroy (di->standalonesig_cache);
5574         for (list = di->array_methods; list; list = list->next) {
5575                 ArrayMethod *am = (ArrayMethod *)list->data;
5576                 g_free (am->sig);
5577                 g_free (am->name);
5578                 g_free (am);
5579         }
5580         g_list_free (di->array_methods);
5581         if (di->gen_params) {
5582                 for (i = 0; i < di->gen_params->len; i++) {
5583                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5584                         mono_gc_deregister_root ((char*) &entry->gparam);
5585                         g_free (entry);
5586                 }
5587                 g_ptr_array_free (di->gen_params, TRUE);
5588         }
5589         if (di->token_fixups)
5590                 mono_g_hash_table_destroy (di->token_fixups);
5591         if (di->method_to_table_idx)
5592                 g_hash_table_destroy (di->method_to_table_idx);
5593         if (di->field_to_table_idx)
5594                 g_hash_table_destroy (di->field_to_table_idx);
5595         if (di->method_aux_hash)
5596                 g_hash_table_destroy (di->method_aux_hash);
5597         if (di->vararg_aux_hash)
5598                 g_hash_table_destroy (di->vararg_aux_hash);
5599         g_free (di->strong_name);
5600         g_free (di->win32_res);
5601         if (di->public_key)
5602                 g_free (di->public_key);
5603
5604         /*g_print ("string heap destroy for image %p\n", di);*/
5605         mono_dynamic_stream_reset (&di->sheap);
5606         mono_dynamic_stream_reset (&di->code);
5607         mono_dynamic_stream_reset (&di->resources);
5608         mono_dynamic_stream_reset (&di->us);
5609         mono_dynamic_stream_reset (&di->blob);
5610         mono_dynamic_stream_reset (&di->tstream);
5611         mono_dynamic_stream_reset (&di->guid);
5612         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5613                 g_free (di->tables [i].values);
5614         }
5615
5616         dynamic_images_lock ();
5617
5618         if (dynamic_images)
5619                 g_ptr_array_remove (dynamic_images, di);
5620
5621         dynamic_images_unlock ();
5622 }
5623
5624 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5625 void
5626 mono_dynamic_image_free_image (MonoDynamicImage *image)
5627 {
5628         /* See create_dynamic_mono_image () */
5629 #if HAVE_BOEHM_GC
5630         /* Allocated using GC_MALLOC */
5631 #else
5632         g_free (image);
5633 #endif
5634 }
5635
5636 #ifndef DISABLE_REFLECTION_EMIT
5637
5638 /*
5639  * mono_image_basic_init:
5640  * @assembly: an assembly builder object
5641  *
5642  * Create the MonoImage that represents the assembly builder and setup some
5643  * of the helper hash table and the basic metadata streams.
5644  */
5645 void
5646 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5647 {
5648         MonoDynamicAssembly *assembly;
5649         MonoDynamicImage *image;
5650         MonoDomain *domain = mono_object_domain (assemblyb);
5651         
5652         if (assemblyb->dynamic_assembly)
5653                 return;
5654
5655 #if HAVE_BOEHM_GC
5656         /* assembly->assembly.image might be GC allocated */
5657         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5658 #else
5659         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5660 #endif
5661
5662         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5663         
5664         assembly->assembly.ref_count = 1;
5665         assembly->assembly.dynamic = TRUE;
5666         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5667         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5668         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5669         if (assemblyb->culture)
5670                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5671         else
5672                 assembly->assembly.aname.culture = g_strdup ("");
5673
5674         if (assemblyb->version) {
5675                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5676                         char **version = g_strsplit (vstr, ".", 4);
5677                         char **parts = version;
5678                         assembly->assembly.aname.major = atoi (*parts++);
5679                         assembly->assembly.aname.minor = atoi (*parts++);
5680                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5681                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5682
5683                         g_strfreev (version);
5684                         g_free (vstr);
5685         } else {
5686                         assembly->assembly.aname.major = 0;
5687                         assembly->assembly.aname.minor = 0;
5688                         assembly->assembly.aname.build = 0;
5689                         assembly->assembly.aname.revision = 0;
5690         }
5691
5692         assembly->run = assemblyb->access != 2;
5693         assembly->save = assemblyb->access != 1;
5694         assembly->domain = domain;
5695
5696         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5697         image->initial_image = TRUE;
5698         assembly->assembly.aname.name = image->image.name;
5699         assembly->assembly.image = &image->image;
5700         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5701                 /* -1 to correct for the trailing NULL byte */
5702                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5703                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5704                 }
5705                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5706         }
5707
5708         mono_domain_assemblies_lock (domain);
5709         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5710         mono_domain_assemblies_unlock (domain);
5711
5712         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5713         
5714         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5715         
5716         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5717 }
5718
5719 #endif /* !DISABLE_REFLECTION_EMIT */
5720
5721 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5722
5723 static int
5724 calc_section_size (MonoDynamicImage *assembly)
5725 {
5726         int nsections = 0;
5727
5728         /* alignment constraints */
5729         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5730         g_assert ((assembly->code.index % 4) == 0);
5731         assembly->meta_size += 3;
5732         assembly->meta_size &= ~3;
5733         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5734         g_assert ((assembly->resources.index % 4) == 0);
5735
5736         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5737         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5738         nsections++;
5739
5740         if (assembly->win32_res) {
5741                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5742
5743                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5744                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5745                 nsections++;
5746         }
5747
5748         assembly->sections [MONO_SECTION_RELOC].size = 12;
5749         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5750         nsections++;
5751
5752         return nsections;
5753 }
5754
5755 typedef struct {
5756         guint32 id;
5757         guint32 offset;
5758         GSList *children;
5759         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5760 } ResTreeNode;
5761
5762 static int
5763 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5764 {
5765         ResTreeNode *t1 = (ResTreeNode*)a;
5766         ResTreeNode *t2 = (ResTreeNode*)b;
5767
5768         return t1->id - t2->id;
5769 }
5770
5771 /*
5772  * resource_tree_create:
5773  *
5774  *  Organize the resources into a resource tree.
5775  */
5776 static ResTreeNode *
5777 resource_tree_create (MonoArray *win32_resources)
5778 {
5779         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5780         GSList *l;
5781         int i;
5782
5783         tree = g_new0 (ResTreeNode, 1);
5784         
5785         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5786                 MonoReflectionWin32Resource *win32_res =
5787                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5788
5789                 /* Create node */
5790
5791                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5792                 lang_node = g_new0 (ResTreeNode, 1);
5793                 lang_node->id = win32_res->lang_id;
5794                 lang_node->win32_res = win32_res;
5795
5796                 /* Create type node if neccesary */
5797                 type_node = NULL;
5798                 for (l = tree->children; l; l = l->next)
5799                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5800                                 type_node = (ResTreeNode*)l->data;
5801                                 break;
5802                         }
5803
5804                 if (!type_node) {
5805                         type_node = g_new0 (ResTreeNode, 1);
5806                         type_node->id = win32_res->res_type;
5807
5808                         /* 
5809                          * The resource types have to be sorted otherwise
5810                          * Windows Explorer can't display the version information.
5811                          */
5812                         tree->children = g_slist_insert_sorted (tree->children, 
5813                                 type_node, resource_tree_compare_by_id);
5814                 }
5815
5816                 /* Create res node if neccesary */
5817                 res_node = NULL;
5818                 for (l = type_node->children; l; l = l->next)
5819                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5820                                 res_node = (ResTreeNode*)l->data;
5821                                 break;
5822                         }
5823
5824                 if (!res_node) {
5825                         res_node = g_new0 (ResTreeNode, 1);
5826                         res_node->id = win32_res->res_id;
5827                         type_node->children = g_slist_append (type_node->children, res_node);
5828                 }
5829
5830                 res_node->children = g_slist_append (res_node->children, lang_node);
5831         }
5832
5833         return tree;
5834 }
5835
5836 /*
5837  * resource_tree_encode:
5838  * 
5839  *   Encode the resource tree into the format used in the PE file.
5840  */
5841 static void
5842 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5843 {
5844         char *entries;
5845         MonoPEResourceDir dir;
5846         MonoPEResourceDirEntry dir_entry;
5847         MonoPEResourceDataEntry data_entry;
5848         GSList *l;
5849         guint32 res_id_entries;
5850
5851         /*
5852          * For the format of the resource directory, see the article
5853          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5854          * Matt Pietrek
5855          */
5856
5857         memset (&dir, 0, sizeof (dir));
5858         memset (&dir_entry, 0, sizeof (dir_entry));
5859         memset (&data_entry, 0, sizeof (data_entry));
5860
5861         g_assert (sizeof (dir) == 16);
5862         g_assert (sizeof (dir_entry) == 8);
5863         g_assert (sizeof (data_entry) == 16);
5864
5865         node->offset = p - begin;
5866
5867         /* IMAGE_RESOURCE_DIRECTORY */
5868         res_id_entries = g_slist_length (node->children);
5869         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5870
5871         memcpy (p, &dir, sizeof (dir));
5872         p += sizeof (dir);
5873
5874         /* Reserve space for entries */
5875         entries = p;
5876         p += sizeof (dir_entry) * res_id_entries;
5877
5878         /* Write children */
5879         for (l = node->children; l; l = l->next) {
5880                 ResTreeNode *child = (ResTreeNode*)l->data;
5881
5882                 if (child->win32_res) {
5883                         guint32 size;
5884
5885                         child->offset = p - begin;
5886
5887                         /* IMAGE_RESOURCE_DATA_ENTRY */
5888                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5889                         size = mono_array_length (child->win32_res->res_data);
5890                         data_entry.rde_size = GUINT32_TO_LE (size);
5891
5892                         memcpy (p, &data_entry, sizeof (data_entry));
5893                         p += sizeof (data_entry);
5894
5895                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5896                         p += size;
5897                 } else {
5898                         resource_tree_encode (child, begin, p, &p);
5899                 }
5900         }
5901
5902         /* IMAGE_RESOURCE_ENTRY */
5903         for (l = node->children; l; l = l->next) {
5904                 ResTreeNode *child = (ResTreeNode*)l->data;
5905
5906                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5907                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5908
5909                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5910                 entries += sizeof (dir_entry);
5911         }
5912
5913         *endbuf = p;
5914 }
5915
5916 static void
5917 resource_tree_free (ResTreeNode * node)
5918 {
5919         GSList * list;
5920         for (list = node->children; list; list = list->next)
5921                 resource_tree_free ((ResTreeNode*)list->data);
5922         g_slist_free(node->children);
5923         g_free (node);
5924 }
5925
5926 static void
5927 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5928 {
5929         char *buf;
5930         char *p;
5931         guint32 size, i;
5932         MonoReflectionWin32Resource *win32_res;
5933         ResTreeNode *tree;
5934
5935         if (!assemblyb->win32_resources)
5936                 return;
5937
5938         /*
5939          * Resources are stored in a three level tree inside the PE file.
5940          * - level one contains a node for each type of resource
5941          * - level two contains a node for each resource
5942          * - level three contains a node for each instance of a resource for a
5943          *   specific language.
5944          */
5945
5946         tree = resource_tree_create (assemblyb->win32_resources);
5947
5948         /* Estimate the size of the encoded tree */
5949         size = 0;
5950         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5951                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5952                 size += mono_array_length (win32_res->res_data);
5953         }
5954         /* Directory structure */
5955         size += mono_array_length (assemblyb->win32_resources) * 256;
5956         p = buf = (char *)g_malloc (size);
5957
5958         resource_tree_encode (tree, p, p, &p);
5959
5960         g_assert (p - buf <= size);
5961
5962         assembly->win32_res = (char *)g_malloc (p - buf);
5963         assembly->win32_res_size = p - buf;
5964         memcpy (assembly->win32_res, buf, p - buf);
5965
5966         g_free (buf);
5967         resource_tree_free (tree);
5968 }
5969
5970 static void
5971 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5972 {
5973         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5974         int i;
5975
5976         p += sizeof (MonoPEResourceDir);
5977         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5978                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5979                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5980                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5981                         fixup_resource_directory (res_section, child, rva);
5982                 } else {
5983                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5984                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5985                 }
5986
5987                 p += sizeof (MonoPEResourceDirEntry);
5988         }
5989 }
5990
5991 static void
5992 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5993 {
5994         guint32 dummy;
5995         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5996                 g_error ("WriteFile returned %d\n", GetLastError ());
5997 }
5998
5999 /*
6000  * mono_image_create_pefile:
6001  * @mb: a module builder object
6002  * 
6003  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6004  * assembly->pefile where it can be easily retrieved later in chunks.
6005  */
6006 void
6007 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6008 {
6009         MonoError error;
6010         MonoMSDOSHeader *msdos;
6011         MonoDotNetHeader *header;
6012         MonoSectionTable *section;
6013         MonoCLIHeader *cli_header;
6014         guint32 size, image_size, virtual_base, text_offset;
6015         guint32 header_start, section_start, file_offset, virtual_offset;
6016         MonoDynamicImage *assembly;
6017         MonoReflectionAssemblyBuilder *assemblyb;
6018         MonoDynamicStream pefile_stream = {0};
6019         MonoDynamicStream *pefile = &pefile_stream;
6020         int i, nsections;
6021         guint32 *rva, value;
6022         guchar *p;
6023         static const unsigned char msheader[] = {
6024                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6025                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6026                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6027                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6028                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6029                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6030                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6031                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6032         };
6033
6034         assemblyb = mb->assemblyb;
6035
6036         mono_image_basic_init (assemblyb);
6037         assembly = mb->dynamic_image;
6038
6039         assembly->pe_kind = assemblyb->pe_kind;
6040         assembly->machine = assemblyb->machine;
6041         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6042         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6043         
6044         if (!mono_image_build_metadata (mb, &error))
6045                 mono_error_raise_exception (&error); /* FIXME don't raise here */
6046         
6047
6048         if (mb->is_main && assemblyb->resources) {
6049                 int len = mono_array_length (assemblyb->resources);
6050                 for (i = 0; i < len; ++i)
6051                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6052         }
6053
6054         if (mb->resources) {
6055                 int len = mono_array_length (mb->resources);
6056                 for (i = 0; i < len; ++i)
6057                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6058         }
6059
6060         build_compressed_metadata (assembly);
6061
6062         if (mb->is_main)
6063                 assembly_add_win32_resources (assembly, assemblyb);
6064
6065         nsections = calc_section_size (assembly);
6066         
6067         /* The DOS header and stub */
6068         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6069         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6070
6071         /* the dotnet header */
6072         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6073
6074         /* the section tables */
6075         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6076
6077         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6078         virtual_offset = VIRT_ALIGN;
6079         image_size = 0;
6080
6081         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6082                 if (!assembly->sections [i].size)
6083                         continue;
6084                 /* align offsets */
6085                 file_offset += FILE_ALIGN - 1;
6086                 file_offset &= ~(FILE_ALIGN - 1);
6087                 virtual_offset += VIRT_ALIGN - 1;
6088                 virtual_offset &= ~(VIRT_ALIGN - 1);
6089
6090                 assembly->sections [i].offset = file_offset;
6091                 assembly->sections [i].rva = virtual_offset;
6092
6093                 file_offset += assembly->sections [i].size;
6094                 virtual_offset += assembly->sections [i].size;
6095                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6096         }
6097
6098         file_offset += FILE_ALIGN - 1;
6099         file_offset &= ~(FILE_ALIGN - 1);
6100
6101         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6102
6103         /* back-patch info */
6104         msdos = (MonoMSDOSHeader*)pefile->data;
6105         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6106
6107         header = (MonoDotNetHeader*)(pefile->data + header_start);
6108         header->pesig [0] = 'P';
6109         header->pesig [1] = 'E';
6110         
6111         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6112         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6113         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6114         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6115         if (assemblyb->pekind == 1) {
6116                 /* it's a dll */
6117                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6118         } else {
6119                 /* it's an exe */
6120                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6121         }
6122
6123         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6124
6125         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6126         header->pe.pe_major = 6;
6127         header->pe.pe_minor = 0;
6128         size = assembly->sections [MONO_SECTION_TEXT].size;
6129         size += FILE_ALIGN - 1;
6130         size &= ~(FILE_ALIGN - 1);
6131         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6132         size = assembly->sections [MONO_SECTION_RSRC].size;
6133         size += FILE_ALIGN - 1;
6134         size &= ~(FILE_ALIGN - 1);
6135         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6136         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6137         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6138         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6139         /* pe_rva_entry_point always at the beginning of the text section */
6140         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6141
6142         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6143         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6144         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6145         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6146         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6147         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6148         size = section_start;
6149         size += FILE_ALIGN - 1;
6150         size &= ~(FILE_ALIGN - 1);
6151         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6152         size = image_size;
6153         size += VIRT_ALIGN - 1;
6154         size &= ~(VIRT_ALIGN - 1);
6155         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6156
6157         /*
6158         // Translate the PEFileKind value to the value expected by the Windows loader
6159         */
6160         {
6161                 short kind;
6162
6163                 /*
6164                 // PEFileKinds.Dll == 1
6165                 // PEFileKinds.ConsoleApplication == 2
6166                 // PEFileKinds.WindowApplication == 3
6167                 //
6168                 // need to get:
6169                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6170                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6171                 */
6172                 if (assemblyb->pekind == 3)
6173                         kind = 2;
6174                 else
6175                         kind = 3;
6176                 
6177                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6178         }    
6179         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6180         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6181         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6182         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6183         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6184         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6185
6186         /* fill data directory entries */
6187
6188         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6189         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6190
6191         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6192         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6193
6194         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6195         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6196         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6197         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6198         /* patch entrypoint name */
6199         if (assemblyb->pekind == 1)
6200                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6201         else
6202                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6203         /* patch imported function RVA name */
6204         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6205         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6206
6207         /* the import table */
6208         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6209         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6210         /* patch imported dll RVA name and other entries in the dir */
6211         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6212         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6213         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6214         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6215         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6216         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6217
6218         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6219         value = (assembly->text_rva + assembly->imp_names_offset);
6220         *p++ = (value) & 0xff;
6221         *p++ = (value >> 8) & (0xff);
6222         *p++ = (value >> 16) & (0xff);
6223         *p++ = (value >> 24) & (0xff);
6224
6225         /* the CLI header info */
6226         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6227         cli_header->ch_size = GUINT32_FROM_LE (72);
6228         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6229         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6230         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6231         if (assemblyb->entry_point) {
6232                 guint32 table_idx = 0;
6233                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6234                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6235                         table_idx = methodb->table_idx;
6236                 } else {
6237                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6238                 }
6239                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6240         } else {
6241                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6242         }
6243         /* The embedded managed resources */
6244         text_offset = assembly->text_rva + assembly->code.index;
6245         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6246         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6247         text_offset += assembly->resources.index;
6248         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6249         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6250         text_offset += assembly->meta_size;
6251         if (assembly->strong_name_size) {
6252                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6253                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6254                 text_offset += assembly->strong_name_size;
6255         }
6256
6257         /* write the section tables and section content */
6258         section = (MonoSectionTable*)(pefile->data + section_start);
6259         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6260                 static const char section_names [][7] = {
6261                         ".text", ".rsrc", ".reloc"
6262                 };
6263                 if (!assembly->sections [i].size)
6264                         continue;
6265                 strcpy (section->st_name, section_names [i]);
6266                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6267                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6268                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6269                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6270                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6271                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6272                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6273                 section ++;
6274         }
6275         
6276         checked_write_file (file, pefile->data, pefile->index);
6277         
6278         mono_dynamic_stream_reset (pefile);
6279         
6280         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6281                 if (!assembly->sections [i].size)
6282                         continue;
6283                 
6284                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6285                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6286                 
6287                 switch (i) {
6288                 case MONO_SECTION_TEXT:
6289                         /* patch entry point */
6290                         p = (guchar*)(assembly->code.data + 2);
6291                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6292                         *p++ = (value) & 0xff;
6293                         *p++ = (value >> 8) & 0xff;
6294                         *p++ = (value >> 16) & 0xff;
6295                         *p++ = (value >> 24) & 0xff;
6296                 
6297                         checked_write_file (file, assembly->code.data, assembly->code.index);
6298                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6299                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6300                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6301                                 
6302
6303                         g_free (assembly->image.raw_metadata);
6304                         break;
6305                 case MONO_SECTION_RELOC: {
6306                         struct {
6307                                 guint32 page_rva;
6308                                 guint32 block_size;
6309                                 guint16 type_and_offset;
6310                                 guint16 term;
6311                         } reloc;
6312                         
6313                         g_assert (sizeof (reloc) == 12);
6314                         
6315                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6316                         reloc.block_size = GUINT32_FROM_LE (12);
6317                         
6318                         /* 
6319                          * the entrypoint is always at the start of the text section 
6320                          * 3 is IMAGE_REL_BASED_HIGHLOW
6321                          * 2 is patch_size_rva - text_rva
6322                          */
6323                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6324                         reloc.term = 0;
6325                         
6326                         checked_write_file (file, &reloc, sizeof (reloc));
6327                         
6328                         break;
6329                 }
6330                 case MONO_SECTION_RSRC:
6331                         if (assembly->win32_res) {
6332
6333                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6334                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6335                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6336                         }
6337                         break;
6338                 default:
6339                         g_assert_not_reached ();
6340                 }
6341         }
6342         
6343         /* check that the file is properly padded */
6344         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6345                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6346         if (! SetEndOfFile (file))
6347                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6348         
6349         mono_dynamic_stream_reset (&assembly->code);
6350         mono_dynamic_stream_reset (&assembly->us);
6351         mono_dynamic_stream_reset (&assembly->blob);
6352         mono_dynamic_stream_reset (&assembly->guid);
6353         mono_dynamic_stream_reset (&assembly->sheap);
6354
6355         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6356         g_hash_table_destroy (assembly->blob_cache);
6357         assembly->blob_cache = NULL;
6358 }
6359
6360 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6361
6362 void
6363 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6364 {
6365         g_assert_not_reached ();
6366 }
6367
6368 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6369
6370 #ifndef DISABLE_REFLECTION_EMIT
6371
6372 MonoReflectionModule *
6373 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6374 {
6375         char *name;
6376         MonoImage *image;
6377         MonoImageOpenStatus status;
6378         MonoDynamicAssembly *assembly;
6379         guint32 module_count;
6380         MonoImage **new_modules;
6381         gboolean *new_modules_loaded;
6382         
6383         name = mono_string_to_utf8 (fileName);
6384
6385         image = mono_image_open (name, &status);
6386         if (!image) {
6387                 MonoException *exc;
6388                 if (status == MONO_IMAGE_ERROR_ERRNO)
6389                         exc = mono_get_exception_file_not_found (fileName);
6390                 else
6391                         exc = mono_get_exception_bad_image_format (name);
6392                 g_free (name);
6393                 mono_raise_exception (exc);
6394         }
6395
6396         g_free (name);
6397
6398         assembly = ab->dynamic_assembly;
6399         image->assembly = (MonoAssembly*)assembly;
6400
6401         module_count = image->assembly->image->module_count;
6402         new_modules = g_new0 (MonoImage *, module_count + 1);
6403         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6404
6405         if (image->assembly->image->modules)
6406                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6407         if (image->assembly->image->modules_loaded)
6408                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6409         new_modules [module_count] = image;
6410         new_modules_loaded [module_count] = TRUE;
6411         mono_image_addref (image);
6412
6413         g_free (image->assembly->image->modules);
6414         image->assembly->image->modules = new_modules;
6415         image->assembly->image->modules_loaded = new_modules_loaded;
6416         image->assembly->image->module_count ++;
6417
6418         mono_assembly_load_references (image, &status);
6419         if (status) {
6420                 mono_image_close (image);
6421                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6422         }
6423
6424         return mono_module_get_object (mono_domain_get (), image);
6425 }
6426
6427 #endif /* DISABLE_REFLECTION_EMIT */
6428
6429 /*
6430  * We need to return always the same object for MethodInfo, FieldInfo etc..
6431  * but we need to consider the reflected type.
6432  * type uses a different hash, since it uses custom hash/equal functions.
6433  */
6434
6435 typedef struct {
6436         gpointer item;
6437         MonoClass *refclass;
6438 } ReflectedEntry;
6439
6440 static gboolean
6441 reflected_equal (gconstpointer a, gconstpointer b) {
6442         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6443         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6444
6445         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6446 }
6447
6448 static guint
6449 reflected_hash (gconstpointer a) {
6450         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6451         return mono_aligned_addr_hash (ea->item);
6452 }
6453
6454 #define CHECK_OBJECT(t,p,k)     \
6455         do {    \
6456                 t _obj; \
6457                 ReflectedEntry e;       \
6458                 e.item = (p);   \
6459                 e.refclass = (k);       \
6460                 mono_domain_lock (domain);      \
6461                 if (!domain->refobject_hash)    \
6462                         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");  \
6463                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6464                         mono_domain_unlock (domain);    \
6465                         return _obj;    \
6466                 }       \
6467         mono_domain_unlock (domain); \
6468         } while (0)
6469
6470 #ifdef HAVE_BOEHM_GC
6471 /* ReflectedEntry doesn't need to be GC tracked */
6472 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6473 #define FREE_REFENTRY(entry) g_free ((entry))
6474 #define REFENTRY_REQUIRES_CLEANUP
6475 #else
6476 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6477 /* FIXME: */
6478 #define FREE_REFENTRY(entry)
6479 #endif
6480
6481 #define CACHE_OBJECT(t,p,o,k)   \
6482         do {    \
6483                 t _obj; \
6484         ReflectedEntry pe; \
6485         pe.item = (p); \
6486         pe.refclass = (k); \
6487         mono_domain_lock (domain); \
6488                 if (!domain->refobject_hash)    \
6489                         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");  \
6490         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6491         if (!_obj) { \
6492                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6493                     e->item = (p);      \
6494                     e->refclass = (k);  \
6495                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6496             _obj = o; \
6497         } \
6498                 mono_domain_unlock (domain);    \
6499         return _obj; \
6500         } while (0)
6501
6502 static void
6503 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6504 {
6505         mono_domain_lock (domain);
6506         if (domain->refobject_hash) {
6507         ReflectedEntry pe;
6508                 gpointer orig_pe, orig_value;
6509
6510                 pe.item = o;
6511                 pe.refclass = klass;
6512                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6513                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6514                         FREE_REFENTRY (orig_pe);
6515                 }
6516         }
6517         mono_domain_unlock (domain);
6518 }
6519
6520 #ifdef REFENTRY_REQUIRES_CLEANUP
6521 static void
6522 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6523 {
6524         FREE_REFENTRY (key);
6525 }
6526 #endif
6527
6528 void
6529 mono_reflection_cleanup_domain (MonoDomain *domain)
6530 {
6531         if (domain->refobject_hash) {
6532 /*let's avoid scanning the whole hashtable if not needed*/
6533 #ifdef REFENTRY_REQUIRES_CLEANUP
6534                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6535 #endif
6536                 mono_g_hash_table_destroy (domain->refobject_hash);
6537                 domain->refobject_hash = NULL;
6538         }
6539 }
6540
6541 #ifndef DISABLE_REFLECTION_EMIT
6542 static gpointer
6543 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6544 {
6545         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6546 }
6547
6548 static gpointer
6549 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6550 {
6551         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6552 }
6553
6554 void
6555 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6556 {
6557         MonoDynamicImage *image = moduleb->dynamic_image;
6558         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6559         if (!image) {
6560                 MonoError error;
6561                 int module_count;
6562                 MonoImage **new_modules;
6563                 MonoImage *ass;
6564                 char *name, *fqname;
6565                 /*
6566                  * FIXME: we already created an image in mono_image_basic_init (), but
6567                  * we don't know which module it belongs to, since that is only 
6568                  * determined at assembly save time.
6569                  */
6570                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6571                 name = mono_string_to_utf8 (ab->name);
6572                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6573                 if (!mono_error_ok (&error)) {
6574                         g_free (name);
6575                         mono_error_raise_exception (&error);
6576                 }
6577                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6578
6579                 moduleb->module.image = &image->image;
6580                 moduleb->dynamic_image = image;
6581                 register_module (mono_object_domain (moduleb), moduleb, image);
6582
6583                 /* register the module with the assembly */
6584                 ass = ab->dynamic_assembly->assembly.image;
6585                 module_count = ass->module_count;
6586                 new_modules = g_new0 (MonoImage *, module_count + 1);
6587
6588                 if (ass->modules)
6589                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6590                 new_modules [module_count] = &image->image;
6591                 mono_image_addref (&image->image);
6592
6593                 g_free (ass->modules);
6594                 ass->modules = new_modules;
6595                 ass->module_count ++;
6596         }
6597 }
6598
6599 void
6600 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6601 {
6602         MonoDynamicImage *image = moduleb->dynamic_image;
6603
6604         g_assert (type->type);
6605         image->wrappers_type = mono_class_from_mono_type (type->type);
6606 }
6607
6608 #endif
6609
6610 /*
6611  * mono_assembly_get_object:
6612  * @domain: an app domain
6613  * @assembly: an assembly
6614  *
6615  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6616  */
6617 MonoReflectionAssembly*
6618 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6619 {
6620         MonoError error;
6621         static MonoClass *assembly_type;
6622         MonoReflectionAssembly *res;
6623         
6624         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6625         if (!assembly_type) {
6626                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6627                 if (klass == NULL)
6628                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6629                 g_assert (klass);
6630                 assembly_type = klass;
6631         }
6632         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, assembly_type, &error);
6633         mono_error_raise_exception (&error); /* FIXME don't raise here */
6634         res->assembly = assembly;
6635
6636         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6637 }
6638
6639
6640
6641 MonoReflectionModule*   
6642 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6643 {
6644         MonoError error;
6645         static MonoClass *module_type;
6646         MonoReflectionModule *res;
6647         char* basename;
6648         
6649         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6650         if (!module_type) {
6651                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6652                 if (klass == NULL)
6653                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6654                 g_assert (klass);
6655                 module_type = klass;
6656         }
6657         res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6658         mono_error_raise_exception (&error); /* FIXME don't raise here */
6659
6660         res->image = image;
6661         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6662
6663         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6664         basename = g_path_get_basename (image->name);
6665         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6666         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6667         
6668         g_free (basename);
6669
6670         if (image->assembly->image == image) {
6671                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6672         } else {
6673                 int i;
6674                 res->token = 0;
6675                 if (image->assembly->image->modules) {
6676                         for (i = 0; i < image->assembly->image->module_count; i++) {
6677                                 if (image->assembly->image->modules [i] == image)
6678                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6679                         }
6680                         g_assert (res->token);
6681                 }
6682         }
6683
6684         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6685 }
6686
6687 MonoReflectionModule*   
6688 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6689 {
6690         MonoError error;
6691         static MonoClass *module_type;
6692         MonoReflectionModule *res;
6693         MonoTableInfo *table;
6694         guint32 cols [MONO_FILE_SIZE];
6695         const char *name;
6696         guint32 i, name_idx;
6697         const char *val;
6698         
6699         if (!module_type) {
6700                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6701                 if (klass == NULL)
6702                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6703                 g_assert (klass);
6704                 module_type = klass;
6705         }
6706         res = (MonoReflectionModule *)mono_object_new_checked (domain, module_type, &error);
6707         mono_error_raise_exception (&error); /* FIXME don't raise here */
6708
6709         table = &image->tables [MONO_TABLE_FILE];
6710         g_assert (table_index < table->rows);
6711         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6712
6713         res->image = NULL;
6714         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6715         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6716
6717         /* Check whenever the row has a corresponding row in the moduleref table */
6718         table = &image->tables [MONO_TABLE_MODULEREF];
6719         for (i = 0; i < table->rows; ++i) {
6720                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6721                 val = mono_metadata_string_heap (image, name_idx);
6722                 if (strcmp (val, name) == 0)
6723                         res->image = image->modules [i];
6724         }
6725
6726         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6727         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6728         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6729         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6730         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6731
6732         return res;
6733 }
6734
6735 static gboolean
6736 verify_safe_for_managed_space (MonoType *type)
6737 {
6738         switch (type->type) {
6739 #ifdef DEBUG_HARDER
6740         case MONO_TYPE_ARRAY:
6741                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6742         case MONO_TYPE_PTR:
6743                 return verify_safe_for_managed_space (type->data.type);
6744         case MONO_TYPE_SZARRAY:
6745                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6746         case MONO_TYPE_GENERICINST: {
6747                 MonoGenericInst *inst = type->data.generic_class->inst;
6748                 int i;
6749                 if (!inst->is_open)
6750                         break;
6751                 for (i = 0; i < inst->type_argc; ++i)
6752                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6753                                 return FALSE;
6754                 return TRUE;
6755         }
6756 #endif
6757         case MONO_TYPE_VAR:
6758         case MONO_TYPE_MVAR:
6759                 return TRUE;
6760         default:
6761                 return TRUE;
6762         }
6763 }
6764
6765 static MonoType*
6766 mono_type_normalize (MonoType *type)
6767 {
6768         int i;
6769         MonoGenericClass *gclass;
6770         MonoGenericInst *ginst;
6771         MonoClass *gtd;
6772         MonoGenericContainer *gcontainer;
6773         MonoType **argv = NULL;
6774         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6775
6776         if (type->type != MONO_TYPE_GENERICINST)
6777                 return type;
6778
6779         gclass = type->data.generic_class;
6780         ginst = gclass->context.class_inst;
6781         if (!ginst->is_open)
6782                 return type;
6783
6784         gtd = gclass->container_class;
6785         gcontainer = gtd->generic_container;
6786         argv = g_newa (MonoType*, ginst->type_argc);
6787
6788         for (i = 0; i < ginst->type_argc; ++i) {
6789                 MonoType *t = ginst->type_argv [i], *norm;
6790                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6791                         is_denorm_gtd = FALSE;
6792                 norm = mono_type_normalize (t);
6793                 argv [i] = norm;
6794                 if (norm != t)
6795                         requires_rebind = TRUE;
6796         }
6797
6798         if (is_denorm_gtd)
6799                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6800
6801         if (requires_rebind) {
6802                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6803                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6804         }
6805
6806         return type;
6807 }
6808 /*
6809  * mono_type_get_object:
6810  * @domain: an app domain
6811  * @type: a type
6812  *
6813  * Return an System.MonoType object representing the type @type.
6814  */
6815 MonoReflectionType*
6816 mono_type_get_object (MonoDomain *domain, MonoType *type)
6817 {
6818         MonoError error;
6819         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6820         mono_error_raise_exception (&error);
6821
6822         return ret;
6823 }
6824
6825 MonoReflectionType*
6826 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6827 {
6828         MonoType *norm_type;
6829         MonoReflectionType *res;
6830         MonoClass *klass;
6831
6832         mono_error_init (error);
6833
6834         klass = mono_class_from_mono_type (type);
6835
6836         /*we must avoid using @type as it might have come
6837          * from a mono_metadata_type_dup and the caller
6838          * expects that is can be freed.
6839          * Using the right type from 
6840          */
6841         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6842
6843         /* void is very common */
6844         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6845                 return (MonoReflectionType*)domain->typeof_void;
6846
6847         /*
6848          * If the vtable of the given class was already created, we can use
6849          * the MonoType from there and avoid all locking and hash table lookups.
6850          * 
6851          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6852          * that the resulting object is different.   
6853          */
6854         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6855                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6856                 if (vtable && vtable->type)
6857                         return (MonoReflectionType *)vtable->type;
6858         }
6859
6860         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6861         mono_domain_lock (domain);
6862         if (!domain->type_hash)
6863                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6864                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6865         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6866                 mono_domain_unlock (domain);
6867                 mono_loader_unlock ();
6868                 return res;
6869         }
6870
6871         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6872          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6873          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6874          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6875          * artifact of how generics are encoded and should be transparent to managed code so we
6876          * need to weed out this diference when retrieving managed System.Type objects.
6877          */
6878         norm_type = mono_type_normalize (type);
6879         if (norm_type != type) {
6880                 res = mono_type_get_object_checked (domain, norm_type, error);
6881                 if (!mono_error_ok (error))
6882                         return NULL;
6883                 mono_g_hash_table_insert (domain->type_hash, type, res);
6884                 mono_domain_unlock (domain);
6885                 mono_loader_unlock ();
6886                 return res;
6887         }
6888
6889         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6890         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6891                 g_assert (0);
6892
6893         if (!verify_safe_for_managed_space (type)) {
6894                 mono_domain_unlock (domain);
6895                 mono_loader_unlock ();
6896                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6897                 return NULL;
6898         }
6899
6900         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6901                 gboolean is_type_done = TRUE;
6902                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6903                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6904                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6905                 */
6906                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6907                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6908
6909                         if (gparam->owner && gparam->owner->is_method) {
6910                                 MonoMethod *method = gparam->owner->owner.method;
6911                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6912                                         is_type_done = FALSE;
6913                         } else if (gparam->owner && !gparam->owner->is_method) {
6914                                 MonoClass *klass = gparam->owner->owner.klass;
6915                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6916                                         is_type_done = FALSE;
6917                         }
6918                 } 
6919
6920                 /* g_assert_not_reached (); */
6921                 /* should this be considered an error condition? */
6922                 if (is_type_done && !type->byref) {
6923                         mono_domain_unlock (domain);
6924                         mono_loader_unlock ();
6925                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
6926                 }
6927         }
6928         /* This is stored in vtables/JITted code so it has to be pinned */
6929         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6930         if (!mono_error_ok (error))
6931                 return NULL;
6932
6933         res->type = type;
6934         mono_g_hash_table_insert (domain->type_hash, type, res);
6935
6936         if (type->type == MONO_TYPE_VOID)
6937                 domain->typeof_void = (MonoObject*)res;
6938
6939         mono_domain_unlock (domain);
6940         mono_loader_unlock ();
6941         return res;
6942 }
6943
6944 /*
6945  * mono_method_get_object:
6946  * @domain: an app domain
6947  * @method: a method
6948  * @refclass: the reflected type (can be NULL)
6949  *
6950  * Return an System.Reflection.MonoMethod object representing the method @method.
6951  */
6952 MonoReflectionMethod*
6953 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6954 {
6955         MonoError error;
6956         MonoReflectionMethod *ret = NULL;
6957         ret = mono_method_get_object_checked (domain, method, refclass, &error);
6958         mono_error_raise_exception (&error);
6959         return ret;
6960 }
6961
6962 /*
6963  * mono_method_get_object_checked:
6964  * @domain: an app domain
6965  * @method: a method
6966  * @refclass: the reflected type (can be NULL)
6967  * @error: set on error.
6968  *
6969  * Return an System.Reflection.MonoMethod object representing the method @method.
6970  * Returns NULL and sets @error on error.
6971  */
6972 MonoReflectionMethod*
6973 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
6974 {
6975         /*
6976          * We use the same C representation for methods and constructors, but the type 
6977          * name in C# is different.
6978          */
6979         static MonoClass *System_Reflection_MonoMethod = NULL;
6980         static MonoClass *System_Reflection_MonoCMethod = NULL;
6981         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6982         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6983         MonoReflectionType *rt;
6984         MonoClass *klass;
6985         MonoReflectionMethod *ret;
6986
6987         mono_error_init (error);
6988
6989         if (method->is_inflated) {
6990                 MonoReflectionGenericMethod *gret;
6991
6992                 if (!refclass)
6993                         refclass = method->klass;
6994                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6995                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6996                         if (!System_Reflection_MonoGenericCMethod) {
6997                                 System_Reflection_MonoGenericCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod", error);
6998                                 if (!mono_error_ok (error))
6999                                         goto leave;
7000                         }
7001                         klass = System_Reflection_MonoGenericCMethod;
7002                 } else {
7003                         if (!System_Reflection_MonoGenericMethod) {
7004                                 System_Reflection_MonoGenericMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod", error);
7005                                 if (!mono_error_ok (error))
7006                                         goto leave;
7007                         }
7008                         klass = System_Reflection_MonoGenericMethod;
7009                 }
7010                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7011                 if (!mono_error_ok (error))
7012                         goto leave;
7013                 gret->method.method = method;
7014
7015                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7016
7017                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7018                 if (!mono_error_ok (error))
7019                     goto leave;
7020
7021                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7022
7023                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7024         }
7025
7026         if (!refclass)
7027                 refclass = method->klass;
7028
7029         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7030         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7031                 if (!System_Reflection_MonoCMethod) {
7032                         System_Reflection_MonoCMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoCMethod", error);
7033                         if (!mono_error_ok (error))
7034                                 goto leave;
7035                 }
7036                 klass = System_Reflection_MonoCMethod;
7037         }
7038         else {
7039                 if (!System_Reflection_MonoMethod) {
7040                         System_Reflection_MonoMethod = mono_class_from_name_checked (mono_defaults.corlib, "System.Reflection", "MonoMethod", error);
7041                         if (!mono_error_ok (error))
7042                                 goto leave;
7043                 }
7044                 klass = System_Reflection_MonoMethod;
7045         }
7046         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7047         if (!mono_error_ok (error))
7048                 goto leave;
7049         ret->method = method;
7050
7051         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7052         if (!mono_error_ok (error))
7053                 goto leave;
7054
7055         MONO_OBJECT_SETREF (ret, reftype, rt);
7056
7057         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7058
7059 leave:
7060         g_assert (!mono_error_ok (error));
7061         return NULL;
7062 }
7063
7064 /*
7065  * mono_method_clear_object:
7066  *
7067  *   Clear the cached reflection objects for the dynamic method METHOD.
7068  */
7069 void
7070 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7071 {
7072         MonoClass *klass;
7073         g_assert (method_is_dynamic (method));
7074
7075         klass = method->klass;
7076         while (klass) {
7077                 clear_cached_object (domain, method, klass);
7078                 klass = klass->parent;
7079         }
7080         /* Added by mono_param_get_objects () */
7081         clear_cached_object (domain, &(method->signature), NULL);
7082         klass = method->klass;
7083         while (klass) {
7084                 clear_cached_object (domain, &(method->signature), klass);
7085                 klass = klass->parent;
7086         }
7087 }
7088
7089 /*
7090  * mono_field_get_object:
7091  * @domain: an app domain
7092  * @klass: a type
7093  * @field: a field
7094  *
7095  * Return an System.Reflection.MonoField object representing the field @field
7096  * in class @klass.
7097  */
7098 MonoReflectionField*
7099 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7100 {
7101         MonoError error;
7102         MonoReflectionField *result;
7103         result = mono_field_get_object_checked (domain, klass, field, &error);
7104         mono_error_raise_exception (&error);
7105         return result;
7106 }
7107
7108 /*
7109  * mono_field_get_object_checked:
7110  * @domain: an app domain
7111  * @klass: a type
7112  * @field: a field
7113  * @error: set on error
7114  *
7115  * Return an System.Reflection.MonoField object representing the field @field
7116  * in class @klass. On error, returns NULL and sets @error.
7117  */
7118 MonoReflectionField*
7119 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7120 {
7121         MonoReflectionType *rt;
7122         MonoReflectionField *res;
7123         static MonoClass *monofield_klass;
7124
7125         mono_error_init (error);
7126
7127         CHECK_OBJECT (MonoReflectionField *, field, klass);
7128         if (!monofield_klass)
7129                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
7130         res = (MonoReflectionField *)mono_object_new_checked (domain, monofield_klass, error);
7131         mono_error_raise_exception (error); /* FIXME don't raise here */
7132         res->klass = klass;
7133         res->field = field;
7134         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7135
7136         if (is_field_on_inst (field)) {
7137                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7138
7139                 rt = mono_type_get_object_checked (domain, field->type, error);
7140                 if (!mono_error_ok (error))
7141                         return NULL;
7142
7143                 MONO_OBJECT_SETREF (res, type, rt);
7144         } else {
7145                 if (field->type) {
7146                         rt = mono_type_get_object_checked (domain, field->type, error);
7147                         if (!mono_error_ok (error))
7148                                 return NULL;
7149
7150                         MONO_OBJECT_SETREF (res, type, rt);
7151                 }
7152                 res->attrs = mono_field_get_flags (field);
7153         }
7154         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7155 }
7156
7157 /*
7158  * mono_property_get_object:
7159  * @domain: an app domain
7160  * @klass: a type
7161  * @property: a property
7162  *
7163  * Return an System.Reflection.MonoProperty object representing the property @property
7164  * in class @klass.
7165  */
7166 MonoReflectionProperty*
7167 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7168 {
7169         MonoError error;
7170         MonoReflectionProperty *res;
7171         static MonoClass *monoproperty_klass;
7172
7173         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7174         if (!monoproperty_klass)
7175                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7176         res = (MonoReflectionProperty *)mono_object_new_checked (domain, monoproperty_klass, &error);
7177         mono_error_raise_exception (&error); /* FIXME don't raise here */
7178         res->klass = klass;
7179         res->property = property;
7180         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7181 }
7182
7183 /*
7184  * mono_event_get_object:
7185  * @domain: an app domain
7186  * @klass: a type
7187  * @event: a event
7188  *
7189  * Return an System.Reflection.MonoEvent object representing the event @event
7190  * in class @klass.
7191  */
7192 MonoReflectionEvent*
7193 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7194 {
7195         MonoError error;
7196         MonoReflectionEvent *res;
7197         MonoReflectionMonoEvent *mono_event;
7198         static MonoClass *monoevent_klass;
7199
7200         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7201         if (!monoevent_klass)
7202                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7203         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, monoevent_klass, &error);
7204         mono_error_raise_exception (&error); /* FIXME don't raise here */
7205         mono_event->klass = klass;
7206         mono_event->event = event;
7207         res = (MonoReflectionEvent*)mono_event;
7208         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7209 }
7210
7211 /**
7212  * mono_get_reflection_missing_object:
7213  * @domain: Domain where the object lives
7214  *
7215  * Returns the System.Reflection.Missing.Value singleton object
7216  * (of type System.Reflection.Missing).
7217  *
7218  * Used as the value for ParameterInfo.DefaultValue when Optional
7219  * is present
7220  */
7221 static MonoObject *
7222 mono_get_reflection_missing_object (MonoDomain *domain)
7223 {
7224         MonoObject *obj;
7225         static MonoClassField *missing_value_field = NULL;
7226         
7227         if (!missing_value_field) {
7228                 MonoClass *missing_klass;
7229                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7230                 mono_class_init (missing_klass);
7231                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7232                 g_assert (missing_value_field);
7233         }
7234         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7235         g_assert (obj);
7236         return obj;
7237 }
7238
7239 static MonoObject*
7240 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7241 {
7242         if (!*dbnull)
7243                 *dbnull = mono_get_dbnull_object (domain);
7244         return *dbnull;
7245 }
7246
7247 static MonoObject*
7248 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7249 {
7250         if (!*reflection_missing)
7251                 *reflection_missing = mono_get_reflection_missing_object (domain);
7252         return *reflection_missing;
7253 }
7254
7255 /*
7256  * mono_param_get_objects:
7257  * @domain: an app domain
7258  * @method: a method
7259  *
7260  * Return an System.Reflection.ParameterInfo array object representing the parameters
7261  * in the method @method.
7262  */
7263 MonoArray*
7264 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7265 {
7266         static MonoClass *System_Reflection_ParameterInfo;
7267         static MonoClass *System_Reflection_ParameterInfo_array;
7268         MonoError error;
7269         MonoArray *res = NULL;
7270         MonoReflectionMethod *member = NULL;
7271         MonoReflectionParameter *param = NULL;
7272         char **names, **blobs = NULL;
7273         guint32 *types = NULL;
7274         MonoType *type = NULL;
7275         MonoObject *dbnull = NULL;
7276         MonoObject *missing = NULL;
7277         MonoMarshalSpec **mspecs;
7278         MonoMethodSignature *sig;
7279         MonoVTable *pinfo_vtable;
7280         MonoReflectionType *rt;
7281         int i;
7282
7283         if (!System_Reflection_ParameterInfo_array) {
7284                 MonoClass *klass;
7285
7286                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7287                 if (!klass)
7288                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7289
7290                 mono_memory_barrier ();
7291                 System_Reflection_ParameterInfo = klass; 
7292
7293         
7294                 klass = mono_array_class_get (klass, 1);
7295                 mono_memory_barrier ();
7296                 System_Reflection_ParameterInfo_array = klass;
7297         }
7298
7299         sig = mono_method_signature_checked (method, &error);
7300         if (!mono_error_ok (&error))
7301                 mono_error_raise_exception (&error);
7302
7303         if (!sig->param_count) {
7304                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7305                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7306
7307                 return res;
7308         }
7309
7310         /* Note: the cache is based on the address of the signature into the method
7311          * since we already cache MethodInfos with the method as keys.
7312          */
7313         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7314
7315         member = mono_method_get_object_checked (domain, method, refclass, &error);
7316         mono_error_raise_exception (&error); /* FIXME don't raise here */
7317         names = g_new (char *, sig->param_count);
7318         mono_method_get_param_names (method, (const char **) names);
7319
7320         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7321         mono_method_get_marshal_info (method, mspecs);
7322
7323         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7324         mono_error_raise_exception (&error); /* FIXME don't raise here */
7325
7326         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7327         for (i = 0; i < sig->param_count; ++i) {
7328                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7329                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7330
7331                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7332                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7333
7334                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7335
7336                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7337
7338                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7339
7340                 param->PositionImpl = i;
7341                 param->AttrsImpl = sig->params [i]->attrs;
7342
7343                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7344                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7345                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7346                         else
7347                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7348                 } else {
7349
7350                         if (!blobs) {
7351                                 blobs = g_new0 (char *, sig->param_count);
7352                                 types = g_new0 (guint32, sig->param_count);
7353                                 get_default_param_value_blobs (method, blobs, types); 
7354                         }
7355
7356                         /* Build MonoType for the type from the Constant Table */
7357                         if (!type)
7358                                 type = g_new0 (MonoType, 1);
7359                         type->type = (MonoTypeEnum)types [i];
7360                         type->data.klass = NULL;
7361                         if (types [i] == MONO_TYPE_CLASS)
7362                                 type->data.klass = mono_defaults.object_class;
7363                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7364                                 /* For enums, types [i] contains the base type */
7365
7366                                         type->type = MONO_TYPE_VALUETYPE;
7367                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7368                         } else
7369                                 type->data.klass = mono_class_from_mono_type (type);
7370
7371                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7372
7373                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7374                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7375                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7376                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7377                                 else
7378                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7379                         }
7380                         
7381                 }
7382
7383                 if (mspecs [i + 1])
7384                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7385                 
7386                 mono_array_setref (res, i, param);
7387         }
7388         g_free (names);
7389         g_free (blobs);
7390         g_free (types);
7391         g_free (type);
7392
7393         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7394                 if (mspecs [i])
7395                         mono_metadata_free_marshal_spec (mspecs [i]);
7396         g_free (mspecs);
7397         
7398         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7399 }
7400
7401 MonoArray*
7402 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7403 {
7404         return mono_param_get_objects_internal (domain, method, NULL);
7405 }
7406
7407 /*
7408  * mono_method_body_get_object:
7409  * @domain: an app domain
7410  * @method: a method
7411  *
7412  * Return an System.Reflection.MethodBody object representing the method @method.
7413  */
7414 MonoReflectionMethodBody*
7415 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7416 {
7417         static MonoClass *System_Reflection_MethodBody = NULL;
7418         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7419         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7420         MonoError error;
7421         MonoReflectionMethodBody *ret;
7422         MonoMethodHeader *header;
7423         MonoImage *image;
7424         MonoReflectionType *rt;
7425         guint32 method_rva, local_var_sig_token;
7426     char *ptr;
7427         unsigned char format, flags;
7428         int i;
7429
7430         /* for compatibility with .net */
7431     if (method_is_dynamic (method))
7432         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7433
7434         if (!System_Reflection_MethodBody)
7435                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7436         if (!System_Reflection_LocalVariableInfo)
7437                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7438         if (!System_Reflection_ExceptionHandlingClause)
7439                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7440
7441         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7442
7443         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7444                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7445             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7446                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7447             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7448                 return NULL;
7449
7450         image = method->klass->image;
7451         header = mono_method_get_header (method);
7452
7453         if (!image_is_dynamic (image)) {
7454                 /* Obtain local vars signature token */
7455                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7456                 ptr = mono_image_rva_map (image, method_rva);
7457                 flags = *(const unsigned char *) ptr;
7458                 format = flags & METHOD_HEADER_FORMAT_MASK;
7459                 switch (format){
7460                 case METHOD_HEADER_TINY_FORMAT:
7461                         local_var_sig_token = 0;
7462                         break;
7463                 case METHOD_HEADER_FAT_FORMAT:
7464                         ptr += 2;
7465                         ptr += 2;
7466                         ptr += 4;
7467                         local_var_sig_token = read32 (ptr);
7468                         break;
7469                 default:
7470                         g_assert_not_reached ();
7471                 }
7472         } else
7473                 local_var_sig_token = 0; //FIXME
7474
7475         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, System_Reflection_MethodBody, &error);
7476         mono_error_raise_exception (&error); /* FIXME don't raise here */
7477
7478         ret->init_locals = header->init_locals;
7479         ret->max_stack = header->max_stack;
7480         ret->local_var_sig_token = local_var_sig_token;
7481         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7482         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7483
7484         /* Locals */
7485         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7486         for (i = 0; i < header->num_locals; ++i) {
7487                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, System_Reflection_LocalVariableInfo, &error);
7488                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7489
7490                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7491                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7492
7493                 MONO_OBJECT_SETREF (info, local_type, rt);
7494
7495                 info->is_pinned = header->locals [i]->pinned;
7496                 info->local_index = i;
7497                 mono_array_setref (ret->locals, i, info);
7498         }
7499
7500         /* Exceptions */
7501         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7502         for (i = 0; i < header->num_clauses; ++i) {
7503                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, System_Reflection_ExceptionHandlingClause, &error);
7504                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7505                 MonoExceptionClause *clause = &header->clauses [i];
7506
7507                 info->flags = clause->flags;
7508                 info->try_offset = clause->try_offset;
7509                 info->try_length = clause->try_len;
7510                 info->handler_offset = clause->handler_offset;
7511                 info->handler_length = clause->handler_len;
7512                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7513                         info->filter_offset = clause->data.filter_offset;
7514                 else if (clause->data.catch_class) {
7515                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7516                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7517
7518                         MONO_OBJECT_SETREF (info, catch_type, rt);
7519                 }
7520
7521                 mono_array_setref (ret->clauses, i, info);
7522         }
7523
7524         mono_metadata_free_mh (header);
7525         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7526         return ret;
7527 }
7528
7529 /**
7530  * mono_get_dbnull_object:
7531  * @domain: Domain where the object lives
7532  *
7533  * Returns the System.DBNull.Value singleton object
7534  *
7535  * Used as the value for ParameterInfo.DefaultValue 
7536  */
7537 MonoObject *
7538 mono_get_dbnull_object (MonoDomain *domain)
7539 {
7540         MonoObject *obj;
7541         static MonoClassField *dbnull_value_field = NULL;
7542         
7543         if (!dbnull_value_field) {
7544                 MonoClass *dbnull_klass;
7545                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7546                 mono_class_init (dbnull_klass);
7547                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7548                 g_assert (dbnull_value_field);
7549         }
7550         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7551         g_assert (obj);
7552         return obj;
7553 }
7554
7555 static void
7556 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7557 {
7558         guint32 param_index, i, lastp, crow = 0;
7559         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7560         gint32 idx;
7561
7562         MonoClass *klass = method->klass;
7563         MonoImage *image = klass->image;
7564         MonoMethodSignature *methodsig = mono_method_signature (method);
7565
7566         MonoTableInfo *constt;
7567         MonoTableInfo *methodt;
7568         MonoTableInfo *paramt;
7569
7570         if (!methodsig->param_count)
7571                 return;
7572
7573         mono_class_init (klass);
7574
7575         if (image_is_dynamic (klass->image)) {
7576                 MonoReflectionMethodAux *aux;
7577                 if (method->is_inflated)
7578                         method = ((MonoMethodInflated*)method)->declaring;
7579                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7580                 if (aux && aux->param_defaults) {
7581                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7582                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7583                 }
7584                 return;
7585         }
7586
7587         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7588         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7589         constt = &image->tables [MONO_TABLE_CONSTANT];
7590
7591         idx = mono_method_get_index (method) - 1;
7592         g_assert (idx != -1);
7593
7594         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7595         if (idx + 1 < methodt->rows)
7596                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7597         else
7598                 lastp = paramt->rows + 1;
7599
7600         for (i = param_index; i < lastp; ++i) {
7601                 guint32 paramseq;
7602
7603                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7604                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7605
7606                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7607                         continue;
7608
7609                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7610                 if (!crow) {
7611                         continue;
7612                 }
7613         
7614                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7615                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7616                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7617         }
7618
7619         return;
7620 }
7621
7622 MonoObject *
7623 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7624 {
7625         MonoError error;
7626         void *retval;
7627         MonoClass *klass;
7628         MonoObject *object;
7629         MonoType *basetype = type;
7630
7631         if (!blob)
7632                 return NULL;
7633         
7634         klass = mono_class_from_mono_type (type);
7635         if (klass->valuetype) {
7636                 object = mono_object_new_checked (domain, klass, &error);
7637                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7638                 retval = ((gchar *) object + sizeof (MonoObject));
7639                 if (klass->enumtype)
7640                         basetype = mono_class_enum_basetype (klass);
7641         } else {
7642                 retval = &object;
7643         }
7644                         
7645         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7646                 return object;
7647         else
7648                 return NULL;
7649 }
7650
7651 static int
7652 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7653         int found_sep;
7654         char *s;
7655         gboolean quoted = FALSE;
7656
7657         memset (assembly, 0, sizeof (MonoAssemblyName));
7658         assembly->culture = "";
7659         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7660
7661         if (*p == '"') {
7662                 quoted = TRUE;
7663                 p++;
7664         }
7665         assembly->name = p;
7666         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7667                 p++;
7668         if (quoted) {
7669                 if (*p != '"')
7670                         return 1;
7671                 *p = 0;
7672                 p++;
7673         }
7674         if (*p != ',')
7675                 return 1;
7676         *p = 0;
7677         /* Remove trailing whitespace */
7678         s = p - 1;
7679         while (*s && g_ascii_isspace (*s))
7680                 *s-- = 0;
7681         p ++;
7682         while (g_ascii_isspace (*p))
7683                 p++;
7684         while (*p) {
7685                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7686                         p += 8;
7687                         assembly->major = strtoul (p, &s, 10);
7688                         if (s == p || *s != '.')
7689                                 return 1;
7690                         p = ++s;
7691                         assembly->minor = strtoul (p, &s, 10);
7692                         if (s == p || *s != '.')
7693                                 return 1;
7694                         p = ++s;
7695                         assembly->build = strtoul (p, &s, 10);
7696                         if (s == p || *s != '.')
7697                                 return 1;
7698                         p = ++s;
7699                         assembly->revision = strtoul (p, &s, 10);
7700                         if (s == p)
7701                                 return 1;
7702                         p = s;
7703                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7704                         p += 8;
7705                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7706                                 assembly->culture = "";
7707                                 p += 7;
7708                         } else {
7709                                 assembly->culture = p;
7710                                 while (*p && *p != ',') {
7711                                         p++;
7712                                 }
7713                         }
7714                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7715                         p += 15;
7716                         if (strncmp (p, "null", 4) == 0) {
7717                                 p += 4;
7718                         } else {
7719                                 int len;
7720                                 gchar *start = p;
7721                                 while (*p && *p != ',') {
7722                                         p++;
7723                                 }
7724                                 len = (p - start + 1);
7725                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7726                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7727                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7728                         }
7729                 } else {
7730                         while (*p && *p != ',')
7731                                 p++;
7732                 }
7733                 found_sep = 0;
7734                 while (g_ascii_isspace (*p) || *p == ',') {
7735                         *p++ = 0;
7736                         found_sep = 1;
7737                         continue;
7738                 }
7739                 /* failed */
7740                 if (!found_sep)
7741                         return 1;
7742         }
7743
7744         return 0;
7745 }
7746
7747 /*
7748  * mono_reflection_parse_type:
7749  * @name: type name
7750  *
7751  * Parse a type name as accepted by the GetType () method and output the info
7752  * extracted in the info structure.
7753  * the name param will be mangled, so, make a copy before passing it to this function.
7754  * The fields in info will be valid until the memory pointed to by name is valid.
7755  *
7756  * See also mono_type_get_name () below.
7757  *
7758  * Returns: 0 on parse error.
7759  */
7760 static int
7761 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7762                              MonoTypeNameParse *info)
7763 {
7764         char *start, *p, *w, *last_point, *startn;
7765         int in_modifiers = 0;
7766         int isbyref = 0, rank = 0, isptr = 0;
7767
7768         start = p = w = name;
7769
7770         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7771         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7772         info->name = info->name_space = NULL;
7773         info->nested = NULL;
7774         info->modifiers = NULL;
7775         info->type_arguments = NULL;
7776
7777         /* last_point separates the namespace from the name */
7778         last_point = NULL;
7779         /* Skips spaces */
7780         while (*p == ' ') p++, start++, w++, name++;
7781
7782         while (*p) {
7783                 switch (*p) {
7784                 case '+':
7785                         *p = 0; /* NULL terminate the name */
7786                         startn = p + 1;
7787                         info->nested = g_list_append (info->nested, startn);
7788                         /* we have parsed the nesting namespace + name */
7789                         if (info->name)
7790                                 break;
7791                         if (last_point) {
7792                                 info->name_space = start;
7793                                 *last_point = 0;
7794                                 info->name = last_point + 1;
7795                         } else {
7796                                 info->name_space = (char *)"";
7797                                 info->name = start;
7798                         }
7799                         break;
7800                 case '.':
7801                         last_point = p;
7802                         break;
7803                 case '\\':
7804                         ++p;
7805                         break;
7806                 case '&':
7807                 case '*':
7808                 case '[':
7809                 case ',':
7810                 case ']':
7811                         in_modifiers = 1;
7812                         break;
7813                 default:
7814                         break;
7815                 }
7816                 if (in_modifiers)
7817                         break;
7818                 // *w++ = *p++;
7819                 p++;
7820         }
7821         
7822         if (!info->name) {
7823                 if (last_point) {
7824                         info->name_space = start;
7825                         *last_point = 0;
7826                         info->name = last_point + 1;
7827                 } else {
7828                         info->name_space = (char *)"";
7829                         info->name = start;
7830                 }
7831         }
7832         while (*p) {
7833                 switch (*p) {
7834                 case '&':
7835                         if (isbyref) /* only one level allowed by the spec */
7836                                 return 0;
7837                         isbyref = 1;
7838                         isptr = 0;
7839                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7840                         *p++ = 0;
7841                         break;
7842                 case '*':
7843                         if (isbyref) /* pointer to ref not okay */
7844                                 return 0;
7845                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7846                         isptr = 1;
7847                         *p++ = 0;
7848                         break;
7849                 case '[':
7850                         if (isbyref) /* array of ref and generic ref are not okay */
7851                                 return 0;
7852                         //Decide if it's an array of a generic argument list
7853                         *p++ = 0;
7854
7855                         if (!*p) //XXX test
7856                                 return 0;
7857                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7858                                 isptr = 0;
7859                                 rank = 1;
7860                                 while (*p) {
7861                                         if (*p == ']')
7862                                                 break;
7863                                         if (*p == ',')
7864                                                 rank++;
7865                                         else if (*p == '*') /* '*' means unknown lower bound */
7866                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7867                                         else
7868                                                 return 0;
7869                                         ++p;
7870                                 }
7871                                 if (*p++ != ']')
7872                                         return 0;
7873                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7874                         } else {
7875                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7876                                         return 0;
7877                                 isptr = 0;
7878                                 info->type_arguments = g_ptr_array_new ();
7879                                 while (*p) {
7880                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7881                                         gboolean fqname = FALSE;
7882
7883                                         g_ptr_array_add (info->type_arguments, subinfo);
7884
7885                                         while (*p == ' ') p++;
7886                                         if (*p == '[') {
7887                                                 p++;
7888                                                 fqname = TRUE;
7889                                         }
7890
7891                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7892                                                 return 0;
7893
7894                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7895                                         if (fqname && (*p != ']')) {
7896                                                 char *aname;
7897
7898                                                 if (*p != ',')
7899                                                         return 0;
7900                                                 *p++ = 0;
7901
7902                                                 aname = p;
7903                                                 while (*p && (*p != ']'))
7904                                                         p++;
7905
7906                                                 if (*p != ']')
7907                                                         return 0;
7908
7909                                                 *p++ = 0;
7910                                                 while (*aname) {
7911                                                         if (g_ascii_isspace (*aname)) {
7912                                                                 ++aname;
7913                                                                 continue;
7914                                                         }
7915                                                         break;
7916                                                 }
7917                                                 if (!*aname ||
7918                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7919                                                         return 0;
7920                                         } else if (fqname && (*p == ']')) {
7921                                                 *p++ = 0;
7922                                         }
7923                                         if (*p == ']') {
7924                                                 *p++ = 0;
7925                                                 break;
7926                                         } else if (!*p) {
7927                                                 return 0;
7928                                         }
7929                                         *p++ = 0;
7930                                 }
7931                         }
7932                         break;
7933                 case ']':
7934                         if (is_recursed)
7935                                 goto end;
7936                         return 0;
7937                 case ',':
7938                         if (is_recursed)
7939                                 goto end;
7940                         *p++ = 0;
7941                         while (*p) {
7942                                 if (g_ascii_isspace (*p)) {
7943                                         ++p;
7944                                         continue;
7945                                 }
7946                                 break;
7947                         }
7948                         if (!*p)
7949                                 return 0; /* missing assembly name */
7950                         if (!assembly_name_to_aname (&info->assembly, p))
7951                                 return 0;
7952                         break;
7953                 default:
7954                         return 0;
7955                 }
7956                 if (info->assembly.name)
7957                         break;
7958         }
7959         // *w = 0; /* terminate class name */
7960  end:
7961         if (!info->name || !*info->name)
7962                 return 0;
7963         if (endptr)
7964                 *endptr = p;
7965         /* add other consistency checks */
7966         return 1;
7967 }
7968
7969
7970 /**
7971  * mono_identifier_unescape_type_name_chars:
7972  * @identifier: the display name of a mono type
7973  *
7974  * Returns:
7975  *  The name in internal form, that is without escaping backslashes.
7976  *
7977  *  The string is modified in place!
7978  */
7979 char*
7980 mono_identifier_unescape_type_name_chars(char* identifier)
7981 {
7982         char *w, *r;
7983         if (!identifier)
7984                 return NULL;
7985         for (w = r = identifier; *r != 0; r++)
7986         {
7987                 char c = *r;
7988                 if (c == '\\') {
7989                         r++;
7990                         if (*r == 0)
7991                                 break;
7992                         c = *r;
7993                 }
7994                 *w = c;
7995                 w++;
7996         }
7997         if (w != r)
7998                 *w = 0;
7999         return identifier;
8000 }
8001
8002 void
8003 mono_identifier_unescape_info (MonoTypeNameParse* info);
8004
8005 static void
8006 unescape_each_type_argument(void* data, void* user_data)
8007 {
8008         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8009         mono_identifier_unescape_info (info);
8010 }
8011
8012 static void
8013 unescape_each_nested_name (void* data, void* user_data)
8014 {
8015         char* nested_name = (char*) data;
8016         mono_identifier_unescape_type_name_chars(nested_name);
8017 }
8018
8019 /**
8020  * mono_identifier_unescape_info:
8021  *
8022  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8023  *
8024  * Returns: nothing.
8025  *
8026  * Destructively updates the info by unescaping the identifiers that
8027  * comprise the type namespace, name, nested types (if any) and
8028  * generic type arguments (if any).
8029  *
8030  * The resulting info has the names in internal form.
8031  *
8032  */
8033 void
8034 mono_identifier_unescape_info (MonoTypeNameParse *info)
8035 {
8036         if (!info)
8037                 return;
8038         mono_identifier_unescape_type_name_chars(info->name_space);
8039         mono_identifier_unescape_type_name_chars(info->name);
8040         // but don't escape info->assembly
8041         if (info->type_arguments)
8042                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8043         if (info->nested)
8044                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8045 }
8046
8047 int
8048 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8049 {
8050         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8051         if (ok) {
8052                 mono_identifier_unescape_info (info);
8053         }
8054         return ok;
8055 }
8056
8057 static MonoType*
8058 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8059 {
8060         gboolean type_resolve = FALSE;
8061         MonoType *type;
8062         MonoImage *rootimage = image;
8063
8064         if (info->assembly.name) {
8065                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8066                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8067                         /* 
8068                          * This could happen in the AOT compiler case when the search hook is not
8069                          * installed.
8070                          */
8071                         assembly = image->assembly;
8072                 if (!assembly) {
8073                         /* then we must load the assembly ourselve - see #60439 */
8074                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8075                         if (!assembly)
8076                                 return NULL;
8077                 }
8078                 image = assembly->image;
8079         } else if (!image) {
8080                 image = mono_defaults.corlib;
8081         }
8082
8083         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8084         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8085                 image = mono_defaults.corlib;
8086                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8087         }
8088
8089         return type;
8090 }
8091
8092 static MonoType*
8093 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
8094 {
8095         MonoError error;
8096         MonoClass *klass;
8097         GList *mod;
8098         int modval;
8099         gboolean bounded = FALSE;
8100         
8101         if (!image)
8102                 image = mono_defaults.corlib;
8103
8104         if (!rootimage)
8105                 rootimage = mono_defaults.corlib;
8106
8107         if (ignorecase) {
8108                 MonoError error;
8109                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
8110                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
8111         } else {
8112                 klass = mono_class_from_name (image, info->name_space, info->name);
8113         }
8114         if (!klass)
8115                 return NULL;
8116         for (mod = info->nested; mod; mod = mod->next) {
8117                 gpointer iter = NULL;
8118                 MonoClass *parent;
8119
8120                 parent = klass;
8121                 mono_class_init (parent);
8122
8123                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8124                         char *lastp;
8125                         char *nested_name, *nested_nspace;
8126                         gboolean match = TRUE;
8127
8128                         lastp = strrchr ((const char *)mod->data, '.');
8129                         if (lastp) {
8130                                 /* Nested classes can have namespaces */
8131                                 int nspace_len;
8132
8133                                 nested_name = g_strdup (lastp + 1);
8134                                 nspace_len = lastp - (char*)mod->data;
8135                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8136                                 memcpy (nested_nspace, mod->data, nspace_len);
8137                                 nested_nspace [nspace_len] = '\0';
8138
8139                         } else {
8140                                 nested_name = (char *)mod->data;
8141                                 nested_nspace = NULL;
8142                         }
8143
8144                         if (nested_nspace) {
8145                                 if (ignorecase) {
8146                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8147                                                 match = FALSE;
8148                                 } else {
8149                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8150                                                 match = FALSE;
8151                                 }
8152                         }
8153                         if (match) {
8154                                 if (ignorecase) {
8155                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8156                                                 match = FALSE;
8157                                 } else {
8158                                         if (strcmp (klass->name, nested_name) != 0)
8159                                                 match = FALSE;
8160                                 }
8161                         }
8162                         if (lastp) {
8163                                 g_free (nested_name);
8164                                 g_free (nested_nspace);
8165                         }
8166                         if (match)
8167                                 break;
8168                 }
8169
8170                 if (!klass)
8171                         break;
8172         }
8173         if (!klass)
8174                 return NULL;
8175
8176         if (info->type_arguments) {
8177                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8178                 MonoReflectionType *the_type;
8179                 MonoType *instance;
8180                 int i;
8181
8182                 for (i = 0; i < info->type_arguments->len; i++) {
8183                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8184
8185                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8186                         if (!type_args [i]) {
8187                                 g_free (type_args);
8188                                 return NULL;
8189                         }
8190                 }
8191
8192                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8193                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8194
8195                 instance = mono_reflection_bind_generic_parameters (
8196                         the_type, info->type_arguments->len, type_args);
8197
8198                 g_free (type_args);
8199                 if (!instance)
8200                         return NULL;
8201
8202                 klass = mono_class_from_mono_type (instance);
8203         }
8204
8205         for (mod = info->modifiers; mod; mod = mod->next) {
8206                 modval = GPOINTER_TO_UINT (mod->data);
8207                 if (!modval) { /* byref: must be last modifier */
8208                         return &klass->this_arg;
8209                 } else if (modval == -1) {
8210                         klass = mono_ptr_class_get (&klass->byval_arg);
8211                 } else if (modval == -2) {
8212                         bounded = TRUE;
8213                 } else { /* array rank */
8214                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8215                 }
8216         }
8217
8218         return &klass->byval_arg;
8219 }
8220
8221 /*
8222  * mono_reflection_get_type:
8223  * @image: a metadata context
8224  * @info: type description structure
8225  * @ignorecase: flag for case-insensitive string compares
8226  * @type_resolve: whenever type resolve was already tried
8227  *
8228  * Build a MonoType from the type description in @info.
8229  * 
8230  */
8231
8232 MonoType*
8233 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8234         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8235 }
8236
8237 static MonoType*
8238 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8239 {
8240         MonoReflectionAssemblyBuilder *abuilder;
8241         MonoType *type;
8242         int i;
8243
8244         g_assert (assembly_is_dynamic (assembly));
8245         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8246
8247         /* Enumerate all modules */
8248
8249         type = NULL;
8250         if (abuilder->modules) {
8251                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8252                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8253                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8254                         if (type)
8255                                 break;
8256                 }
8257         }
8258
8259         if (!type && abuilder->loaded_modules) {
8260                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8261                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8262                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8263                         if (type)
8264                                 break;
8265                 }
8266         }
8267
8268         return type;
8269 }
8270         
8271 MonoType*
8272 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8273 {
8274         MonoType *type;
8275         MonoReflectionAssembly *assembly;
8276         GString *fullName;
8277         GList *mod;
8278
8279         if (image && image_is_dynamic (image))
8280                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8281         else
8282                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8283         if (type)
8284                 return type;
8285         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8286                 return NULL;
8287
8288         if (type_resolve) {
8289                 if (*type_resolve) 
8290                         return NULL;
8291                 else
8292                         *type_resolve = TRUE;
8293         }
8294         
8295         /* Reconstruct the type name */
8296         fullName = g_string_new ("");
8297         if (info->name_space && (info->name_space [0] != '\0'))
8298                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8299         else
8300                 g_string_printf (fullName, "%s", info->name);
8301         for (mod = info->nested; mod; mod = mod->next)
8302                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8303
8304         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8305         if (assembly) {
8306                 if (assembly_is_dynamic (assembly->assembly))
8307                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8308                 else
8309                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8310                                                                                                           info, ignorecase);
8311         }
8312         g_string_free (fullName, TRUE);
8313         return type;
8314 }
8315
8316 void
8317 mono_reflection_free_type_info (MonoTypeNameParse *info)
8318 {
8319         g_list_free (info->modifiers);
8320         g_list_free (info->nested);
8321
8322         if (info->type_arguments) {
8323                 int i;
8324
8325                 for (i = 0; i < info->type_arguments->len; i++) {
8326                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8327
8328                         mono_reflection_free_type_info (subinfo);
8329                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8330                         g_free (subinfo);
8331                 }
8332
8333                 g_ptr_array_free (info->type_arguments, TRUE);
8334         }
8335 }
8336
8337 /*
8338  * mono_reflection_type_from_name:
8339  * @name: type name.
8340  * @image: a metadata context (can be NULL).
8341  *
8342  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8343  * it defaults to get the type from @image or, if @image is NULL or loading
8344  * from it fails, uses corlib.
8345  * 
8346  */
8347 MonoType*
8348 mono_reflection_type_from_name (char *name, MonoImage *image)
8349 {
8350         MonoType *type = NULL;
8351         MonoTypeNameParse info;
8352         char *tmp;
8353
8354         /* Make a copy since parse_type modifies its argument */
8355         tmp = g_strdup (name);
8356         
8357         /*g_print ("requested type %s\n", str);*/
8358         if (mono_reflection_parse_type (tmp, &info)) {
8359                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8360         }
8361
8362         g_free (tmp);
8363         mono_reflection_free_type_info (&info);
8364         return type;
8365 }
8366
8367 /*
8368  * mono_reflection_get_token:
8369  *
8370  *   Return the metadata token of OBJ which should be an object
8371  * representing a metadata element.
8372  */
8373 guint32
8374 mono_reflection_get_token (MonoObject *obj)
8375 {
8376         MonoClass *klass;
8377         guint32 token = 0;
8378
8379         klass = obj->vtable->klass;
8380
8381         if (strcmp (klass->name, "MethodBuilder") == 0) {
8382                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8383
8384                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8385         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8386                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8387
8388                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8389         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8390                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8391
8392                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8393         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8394                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8395                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8396         } else if (strcmp (klass->name, "MonoType") == 0) {
8397                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8398                 MonoClass *mc = mono_class_from_mono_type (type);
8399                 if (!mono_class_init (mc))
8400                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8401
8402                 token = mc->type_token;
8403         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8404                    strcmp (klass->name, "MonoMethod") == 0 ||
8405                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8406                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8407                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8408                 if (m->method->is_inflated) {
8409                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8410                         return inflated->declaring->token;
8411                 } else {
8412                         token = m->method->token;
8413                 }
8414         } else if (strcmp (klass->name, "MonoField") == 0) {
8415                 MonoReflectionField *f = (MonoReflectionField*)obj;
8416
8417                 if (is_field_on_inst (f->field)) {
8418                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8419
8420                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8421                                 int field_index = f->field - dgclass->fields;
8422                                 MonoObject *obj;
8423
8424                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8425                                 obj = dgclass->field_objects [field_index];
8426                                 return mono_reflection_get_token (obj);
8427                         }
8428                 }
8429                 token = mono_class_get_field_token (f->field);
8430         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8431                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8432
8433                 token = mono_class_get_property_token (p->property);
8434         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8435                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8436
8437                 token = mono_class_get_event_token (p->event);
8438         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8439                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8440                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8441                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8442
8443                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8444         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8445                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8446
8447                 token = m->token;
8448         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8449                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8450         } else {
8451                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8452                 MonoException *ex = mono_get_exception_not_implemented (msg);
8453                 g_free (msg);
8454                 mono_raise_exception (ex);
8455         }
8456
8457         return token;
8458 }
8459
8460 static MonoClass*
8461 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8462 {
8463         char *n;
8464         MonoType *t;
8465         int slen = mono_metadata_decode_value (p, &p);
8466
8467         mono_error_init (error);
8468
8469         n = (char *)g_memdup (p, slen + 1);
8470         n [slen] = 0;
8471         t = mono_reflection_type_from_name (n, image);
8472         if (!t) {
8473                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8474                 /* We don't free n, it's consumed by mono_error */
8475                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8476                 return NULL;
8477         }
8478         g_free (n);
8479         p += slen;
8480         *end = p;
8481         return mono_class_from_mono_type (t);
8482 }
8483
8484 static void*
8485 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8486 {
8487         int slen, type = t->type;
8488         MonoClass *tklass = t->data.klass;
8489
8490         mono_error_init (error);
8491
8492 handle_enum:
8493         switch (type) {
8494         case MONO_TYPE_U1:
8495         case MONO_TYPE_I1:
8496         case MONO_TYPE_BOOLEAN: {
8497                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8498                 *bval = *p;
8499                 *end = p + 1;
8500                 return bval;
8501         }
8502         case MONO_TYPE_CHAR:
8503         case MONO_TYPE_U2:
8504         case MONO_TYPE_I2: {
8505                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8506                 *val = read16 (p);
8507                 *end = p + 2;
8508                 return val;
8509         }
8510 #if SIZEOF_VOID_P == 4
8511         case MONO_TYPE_U:
8512         case MONO_TYPE_I:
8513 #endif
8514         case MONO_TYPE_R4:
8515         case MONO_TYPE_U4:
8516         case MONO_TYPE_I4: {
8517                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8518                 *val = read32 (p);
8519                 *end = p + 4;
8520                 return val;
8521         }
8522 #if SIZEOF_VOID_P == 8
8523         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8524         case MONO_TYPE_I:
8525 #endif
8526         case MONO_TYPE_U8:
8527         case MONO_TYPE_I8: {
8528                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8529                 *val = read64 (p);
8530                 *end = p + 8;
8531                 return val;
8532         }
8533         case MONO_TYPE_R8: {
8534                 double *val = (double *)g_malloc (sizeof (double));
8535                 readr8 (p, val);
8536                 *end = p + 8;
8537                 return val;
8538         }
8539         case MONO_TYPE_VALUETYPE:
8540                 if (t->data.klass->enumtype) {
8541                         type = mono_class_enum_basetype (t->data.klass)->type;
8542                         goto handle_enum;
8543                 } else {
8544                         MonoClass *k =  t->data.klass;
8545                         
8546                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8547                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8548                                 *val = read64 (p);
8549                                 *end = p + 8;
8550                                 return val;
8551                         }
8552                 }
8553                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8554                 break;
8555                 
8556         case MONO_TYPE_STRING:
8557                 if (*p == (char)0xFF) {
8558                         *end = p + 1;
8559                         return NULL;
8560                 }
8561                 slen = mono_metadata_decode_value (p, &p);
8562                 *end = p + slen;
8563                 return mono_string_new_len (mono_domain_get (), p, slen);
8564         case MONO_TYPE_CLASS: {
8565                 MonoReflectionType *rt;
8566                 char *n;
8567                 MonoType *t;
8568                 if (*p == (char)0xFF) {
8569                         *end = p + 1;
8570                         return NULL;
8571                 }
8572 handle_type:
8573                 slen = mono_metadata_decode_value (p, &p);
8574                 n = (char *)g_memdup (p, slen + 1);
8575                 n [slen] = 0;
8576                 t = mono_reflection_type_from_name (n, image);
8577                 if (!t) {
8578                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8579                         /* We don't free n, it's consumed by mono_error */
8580                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8581                         return NULL;
8582                 }
8583                 g_free (n);
8584                 *end = p + slen;
8585
8586                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8587                 if (!mono_error_ok (error))
8588                         return NULL;
8589
8590                 return rt;
8591         }
8592         case MONO_TYPE_OBJECT: {
8593                 char subt = *p++;
8594                 MonoObject *obj;
8595                 MonoClass *subc = NULL;
8596                 void *val;
8597
8598                 if (subt == 0x50) {
8599                         goto handle_type;
8600                 } else if (subt == 0x0E) {
8601                         type = MONO_TYPE_STRING;
8602                         goto handle_enum;
8603                 } else if (subt == 0x1D) {
8604                         MonoType simple_type = {{0}};
8605                         int etype = *p;
8606                         p ++;
8607
8608                         type = MONO_TYPE_SZARRAY;
8609                         if (etype == 0x50) {
8610                                 tklass = mono_defaults.systemtype_class;
8611                         } else if (etype == 0x55) {
8612                                 tklass = load_cattr_enum_type (image, p, &p, error);
8613                                 if (!mono_error_ok (error))
8614                                         return NULL;
8615                         } else {
8616                                 if (etype == 0x51)
8617                                         /* See Partition II, Appendix B3 */
8618                                         etype = MONO_TYPE_OBJECT;
8619                                 simple_type.type = (MonoTypeEnum)etype;
8620                                 tklass = mono_class_from_mono_type (&simple_type);
8621                         }
8622                         goto handle_enum;
8623                 } else if (subt == 0x55) {
8624                         char *n;
8625                         MonoType *t;
8626                         slen = mono_metadata_decode_value (p, &p);
8627                         n = (char *)g_memdup (p, slen + 1);
8628                         n [slen] = 0;
8629                         t = mono_reflection_type_from_name (n, image);
8630                         if (!t) {
8631                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8632                                 /* We don't free n, it's consumed by mono_error */
8633                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8634                                 return NULL;
8635                         }
8636                         g_free (n);
8637                         p += slen;
8638                         subc = mono_class_from_mono_type (t);
8639                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8640                         MonoType simple_type = {{0}};
8641                         simple_type.type = (MonoTypeEnum)subt;
8642                         subc = mono_class_from_mono_type (&simple_type);
8643                 } else {
8644                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8645                 }
8646                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8647                 obj = NULL;
8648                 if (mono_error_ok (error)) {
8649                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8650                         g_assert (!subc->has_references);
8651                         if (mono_error_ok (error))
8652                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8653                 }
8654
8655                 g_free (val);
8656                 return obj;
8657         }
8658         case MONO_TYPE_SZARRAY: {
8659                 MonoArray *arr;
8660                 guint32 i, alen, basetype;
8661                 alen = read32 (p);
8662                 p += 4;
8663                 if (alen == 0xffffffff) {
8664                         *end = p;
8665                         return NULL;
8666                 }
8667                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8668                 basetype = tklass->byval_arg.type;
8669                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8670                         basetype = mono_class_enum_basetype (tklass)->type;
8671                 switch (basetype)
8672                 {
8673                         case MONO_TYPE_U1:
8674                         case MONO_TYPE_I1:
8675                         case MONO_TYPE_BOOLEAN:
8676                                 for (i = 0; i < alen; i++) {
8677                                         MonoBoolean val = *p++;
8678                                         mono_array_set (arr, MonoBoolean, i, val);
8679                                 }
8680                                 break;
8681                         case MONO_TYPE_CHAR:
8682                         case MONO_TYPE_U2:
8683                         case MONO_TYPE_I2:
8684                                 for (i = 0; i < alen; i++) {
8685                                         guint16 val = read16 (p);
8686                                         mono_array_set (arr, guint16, i, val);
8687                                         p += 2;
8688                                 }
8689                                 break;
8690                         case MONO_TYPE_R4:
8691                         case MONO_TYPE_U4:
8692                         case MONO_TYPE_I4:
8693                                 for (i = 0; i < alen; i++) {
8694                                         guint32 val = read32 (p);
8695                                         mono_array_set (arr, guint32, i, val);
8696                                         p += 4;
8697                                 }
8698                                 break;
8699                         case MONO_TYPE_R8:
8700                                 for (i = 0; i < alen; i++) {
8701                                         double val;
8702                                         readr8 (p, &val);
8703                                         mono_array_set (arr, double, i, val);
8704                                         p += 8;
8705                                 }
8706                                 break;
8707                         case MONO_TYPE_U8:
8708                         case MONO_TYPE_I8:
8709                                 for (i = 0; i < alen; i++) {
8710                                         guint64 val = read64 (p);
8711                                         mono_array_set (arr, guint64, i, val);
8712                                         p += 8;
8713                                 }
8714                                 break;
8715                         case MONO_TYPE_CLASS:
8716                         case MONO_TYPE_OBJECT:
8717                         case MONO_TYPE_STRING:
8718                         case MONO_TYPE_SZARRAY:
8719                                 for (i = 0; i < alen; i++) {
8720                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8721                                         if (!mono_error_ok (error))
8722                                                 return NULL;
8723                                         mono_array_setref (arr, i, item);
8724                                 }
8725                                 break;
8726                         default:
8727                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8728                 }
8729                 *end=p;
8730                 return arr;
8731         }
8732         default:
8733                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8734         }
8735         return NULL;
8736 }
8737
8738 static MonoObject*
8739 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8740 {
8741         static MonoClass *klass;
8742         static MonoMethod *ctor;
8743         MonoError error;
8744         MonoObject *retval;
8745         void *params [2], *unboxed;
8746
8747         if (!klass)
8748                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8749         if (!ctor)
8750                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8751         
8752         params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8753         mono_error_raise_exception (&error); /* FIXME don't raise here */
8754
8755         params [1] = val;
8756         retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8757         mono_error_raise_exception (&error); /* FIXME don't raise here */
8758         unboxed = mono_object_unbox (retval);
8759         mono_runtime_invoke (ctor, unboxed, params, NULL);
8760
8761         return retval;
8762 }
8763
8764 static MonoObject*
8765 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8766 {
8767         static MonoClass *klass;
8768         static MonoMethod *ctor;
8769         MonoError error;
8770         MonoObject *retval;
8771         void *unboxed, *params [2];
8772
8773         if (!klass)
8774                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8775         if (!ctor)
8776                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8777
8778         params [0] = minfo;
8779         params [1] = typedarg;
8780         retval = mono_object_new_checked (mono_domain_get (), klass, &error);
8781         mono_error_raise_exception (&error); /* FIXME don't raise here */
8782         unboxed = mono_object_unbox (retval);
8783         mono_runtime_invoke (ctor, unboxed, params, NULL);
8784
8785         return retval;
8786 }
8787
8788 static gboolean
8789 type_is_reference (MonoType *type)
8790 {
8791         switch (type->type) {
8792         case MONO_TYPE_BOOLEAN:
8793         case MONO_TYPE_CHAR:
8794         case MONO_TYPE_U:
8795         case MONO_TYPE_I:
8796         case MONO_TYPE_U1:
8797         case MONO_TYPE_I1:
8798         case MONO_TYPE_U2:
8799         case MONO_TYPE_I2:
8800         case MONO_TYPE_U4:
8801         case MONO_TYPE_I4:
8802         case MONO_TYPE_U8:
8803         case MONO_TYPE_I8:
8804         case MONO_TYPE_R8:
8805         case MONO_TYPE_R4:
8806         case MONO_TYPE_VALUETYPE:
8807                 return FALSE;
8808         default:
8809                 return TRUE;
8810         }
8811 }
8812
8813 static void
8814 free_param_data (MonoMethodSignature *sig, void **params) {
8815         int i;
8816         for (i = 0; i < sig->param_count; ++i) {
8817                 if (!type_is_reference (sig->params [i]))
8818                         g_free (params [i]);
8819         }
8820 }
8821
8822 /*
8823  * Find the field index in the metadata FieldDef table.
8824  */
8825 static guint32
8826 find_field_index (MonoClass *klass, MonoClassField *field) {
8827         int i;
8828
8829         for (i = 0; i < klass->field.count; ++i) {
8830                 if (field == &klass->fields [i])
8831                         return klass->field.first + 1 + i;
8832         }
8833         return 0;
8834 }
8835
8836 /*
8837  * Find the property index in the metadata Property table.
8838  */
8839 static guint32
8840 find_property_index (MonoClass *klass, MonoProperty *property) {
8841         int i;
8842
8843         for (i = 0; i < klass->ext->property.count; ++i) {
8844                 if (property == &klass->ext->properties [i])
8845                         return klass->ext->property.first + 1 + i;
8846         }
8847         return 0;
8848 }
8849
8850 /*
8851  * Find the event index in the metadata Event table.
8852  */
8853 static guint32
8854 find_event_index (MonoClass *klass, MonoEvent *event) {
8855         int i;
8856
8857         for (i = 0; i < klass->ext->event.count; ++i) {
8858                 if (event == &klass->ext->events [i])
8859                         return klass->ext->event.first + 1 + i;
8860         }
8861         return 0;
8862 }
8863
8864 static MonoObject*
8865 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8866 {
8867         const char *p = (const char*)data;
8868         const char *named;
8869         guint32 i, j, num_named;
8870         MonoObject *attr;
8871         void *params_buf [32];
8872         void **params = NULL;
8873         MonoMethodSignature *sig;
8874         MonoObject *exc = NULL;
8875
8876         mono_error_init (error);
8877
8878         mono_class_init (method->klass);
8879
8880         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8881                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8882                 return NULL;
8883         }
8884
8885         if (len == 0) {
8886                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8887                 if (!mono_error_ok (error)) return NULL;
8888                 mono_runtime_invoke (method, attr, NULL, NULL);
8889                 return attr;
8890         }
8891
8892         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8893                 return NULL;
8894
8895         /*g_print ("got attr %s\n", method->klass->name);*/
8896
8897         sig = mono_method_signature (method);
8898         if (sig->param_count < 32) {
8899                 params = params_buf;
8900                 memset (params, 0, sizeof (void*) * sig->param_count);
8901         } else {
8902                 /* Allocate using GC so it gets GC tracking */
8903                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8904         }
8905
8906         /* skip prolog */
8907         p += 2;
8908         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8909                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8910                 if (!mono_error_ok (error))
8911                         goto fail;
8912         }
8913
8914         named = p;
8915         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
8916         if (!mono_error_ok (error)) goto fail;
8917
8918         mono_runtime_invoke (method, attr, params, &exc);
8919         if (exc)
8920                 goto fail;
8921         num_named = read16 (named);
8922         named += 2;
8923         for (j = 0; j < num_named; j++) {
8924                 gint name_len;
8925                 char *name, named_type, data_type;
8926                 named_type = *named++;
8927                 data_type = *named++; /* type of data */
8928                 if (data_type == MONO_TYPE_SZARRAY)
8929                         data_type = *named++;
8930                 if (data_type == MONO_TYPE_ENUM) {
8931                         gint type_len;
8932                         char *type_name;
8933                         type_len = mono_metadata_decode_blob_size (named, &named);
8934                         type_name = (char *)g_malloc (type_len + 1);
8935                         memcpy (type_name, named, type_len);
8936                         type_name [type_len] = 0;
8937                         named += type_len;
8938                         /* FIXME: lookup the type and check type consistency */
8939                         g_free (type_name);
8940                 }
8941                 name_len = mono_metadata_decode_blob_size (named, &named);
8942                 name = (char *)g_malloc (name_len + 1);
8943                 memcpy (name, named, name_len);
8944                 name [name_len] = 0;
8945                 named += name_len;
8946                 if (named_type == 0x53) {
8947                         MonoClassField *field;
8948                         void *val;
8949
8950                         /* how this fail is a blackbox */
8951                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8952                         if (!field) {
8953                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8954                                 g_free (name);
8955                                 goto fail;
8956                         }
8957
8958                         val = load_cattr_value (image, field->type, named, &named, error);
8959                         if (!mono_error_ok (error)) {
8960                                 g_free (name);
8961                                 if (!type_is_reference (field->type))
8962                                         g_free (val);
8963                                 goto fail;
8964                         }
8965
8966                         mono_field_set_value (attr, field, val);
8967                         if (!type_is_reference (field->type))
8968                                 g_free (val);
8969                 } else if (named_type == 0x54) {
8970                         MonoProperty *prop;
8971                         void *pparams [1];
8972                         MonoType *prop_type;
8973
8974                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8975
8976                         if (!prop) {
8977                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8978                                 g_free (name);
8979                                 goto fail;
8980                         }
8981
8982                         if (!prop->set) {
8983                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8984                                 g_free (name);
8985                                 goto fail;
8986                         }
8987
8988                         /* can we have more that 1 arg in a custom attr named property? */
8989                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8990                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8991
8992                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8993                         if (!mono_error_ok (error)) {
8994                                 g_free (name);
8995                                 if (!type_is_reference (prop_type))
8996                                         g_free (pparams [0]);
8997                                 goto fail;
8998                         }
8999
9000
9001                         mono_property_set_value (prop, attr, pparams, NULL);
9002                         if (!type_is_reference (prop_type))
9003                                 g_free (pparams [0]);
9004                 }
9005                 g_free (name);
9006         }
9007
9008         free_param_data (method->signature, params);
9009         if (params != params_buf)
9010                 mono_gc_free_fixed (params);
9011
9012         return attr;
9013
9014 fail:
9015         free_param_data (method->signature, params);
9016         if (params != params_buf)
9017                 mono_gc_free_fixed (params);
9018         if (exc)
9019                 mono_raise_exception ((MonoException*)exc);
9020         return NULL;
9021 }
9022         
9023 /*
9024  * mono_reflection_create_custom_attr_data_args:
9025  *
9026  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9027  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9028  * NAMED_ARG_INFO will contain information about the named arguments.
9029  */
9030 void
9031 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)
9032 {
9033         MonoArray *typedargs, *namedargs;
9034         MonoClass *attrklass;
9035         MonoDomain *domain;
9036         const char *p = (const char*)data;
9037         const char *named;
9038         guint32 i, j, num_named;
9039         CattrNamedArg *arginfo = NULL;
9040
9041         *typed_args = NULL;
9042         *named_args = NULL;
9043         *named_arg_info = NULL;
9044
9045         mono_error_init (error);
9046
9047         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9048                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9049                 return;
9050         }
9051
9052         mono_class_init (method->klass);
9053         
9054         domain = mono_domain_get ();
9055
9056         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9057                 return;
9058
9059         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9060         
9061         /* skip prolog */
9062         p += 2;
9063         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9064                 MonoObject *obj;
9065                 void *val;
9066
9067                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9068                 if (!mono_error_ok (error)) {
9069                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9070                                 g_free (val);
9071                         return;
9072                 }
9073
9074                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9075                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9076                 mono_array_setref (typedargs, i, obj);
9077
9078                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9079                         g_free (val);
9080         }
9081
9082         named = p;
9083         num_named = read16 (named);
9084         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9085         named += 2;
9086         attrklass = method->klass;
9087
9088         arginfo = g_new0 (CattrNamedArg, num_named);
9089         *named_arg_info = arginfo;
9090
9091         for (j = 0; j < num_named; j++) {
9092                 gint name_len;
9093                 char *name, named_type, data_type;
9094                 named_type = *named++;
9095                 data_type = *named++; /* type of data */
9096                 if (data_type == MONO_TYPE_SZARRAY)
9097                         data_type = *named++;
9098                 if (data_type == MONO_TYPE_ENUM) {
9099                         gint type_len;
9100                         char *type_name;
9101                         type_len = mono_metadata_decode_blob_size (named, &named);
9102                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9103                                 goto fail;
9104
9105                         type_name = (char *)g_malloc (type_len + 1);
9106                         memcpy (type_name, named, type_len);
9107                         type_name [type_len] = 0;
9108                         named += type_len;
9109                         /* FIXME: lookup the type and check type consistency */
9110                         g_free (type_name);
9111                 }
9112                 name_len = mono_metadata_decode_blob_size (named, &named);
9113                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9114                         goto fail;
9115                 name = (char *)g_malloc (name_len + 1);
9116                 memcpy (name, named, name_len);
9117                 name [name_len] = 0;
9118                 named += name_len;
9119                 if (named_type == 0x53) {
9120                         MonoObject *obj;
9121                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9122                         void *val;
9123
9124                         if (!field) {
9125                                 g_free (name);
9126                                 goto fail;
9127                         }
9128
9129                         arginfo [j].type = field->type;
9130                         arginfo [j].field = field;
9131
9132                         val = load_cattr_value (image, field->type, named, &named, error);
9133                         if (!mono_error_ok (error)) {
9134                                 if (!type_is_reference (field->type))
9135                                         g_free (val);
9136                                 g_free (name);
9137                                 return;
9138                         }
9139
9140                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9141                         mono_array_setref (namedargs, j, obj);
9142                         if (!type_is_reference (field->type))
9143                                 g_free (val);
9144                 } else if (named_type == 0x54) {
9145                         MonoObject *obj;
9146                         MonoType *prop_type;
9147                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9148                         void *val;
9149
9150                         if (!prop || !prop->set) {
9151                                 g_free (name);
9152                                 goto fail;
9153                         }
9154
9155                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9156                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9157
9158                         arginfo [j].type = prop_type;
9159                         arginfo [j].prop = prop;
9160
9161                         val = load_cattr_value (image, prop_type, named, &named, error);
9162                         if (!mono_error_ok (error)) {
9163                                 if (!type_is_reference (prop_type))
9164                                         g_free (val);
9165                                 g_free (name);
9166                                 return;
9167                         }
9168
9169                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9170                         mono_array_setref (namedargs, j, obj);
9171                         if (!type_is_reference (prop_type))
9172                                 g_free (val);
9173                 }
9174                 g_free (name);
9175         }
9176
9177         *typed_args = typedargs;
9178         *named_args = namedargs;
9179         return;
9180 fail:
9181         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9182         g_free (arginfo);
9183         *named_arg_info = NULL;
9184 }
9185
9186 void
9187 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9188 {
9189         MonoDomain *domain;
9190         MonoArray *typedargs, *namedargs;
9191         MonoImage *image;
9192         MonoMethod *method;
9193         CattrNamedArg *arginfo = NULL;
9194         MonoError error;
9195         int i;
9196
9197         mono_error_init (&error);
9198
9199         *ctor_args = NULL;
9200         *named_args = NULL;
9201
9202         if (len == 0)
9203                 return;
9204
9205         image = assembly->assembly->image;
9206         method = ref_method->method;
9207         domain = mono_object_domain (ref_method);
9208
9209         if (!mono_class_init (method->klass))
9210                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9211
9212         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9213         if (!mono_error_ok (&error))
9214                 goto leave;
9215
9216         if (mono_loader_get_last_error ()) {
9217                 mono_error_set_from_loader_error (&error);
9218                 goto leave;
9219         }
9220
9221         if (!typedargs || !namedargs)
9222                 goto leave;
9223
9224         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9225                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9226                 MonoObject *typedarg;
9227
9228                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9229                 mono_array_setref (typedargs, i, typedarg);
9230         }
9231
9232         for (i = 0; i < mono_array_length (namedargs); ++i) {
9233                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9234                 MonoObject *typedarg, *namedarg, *minfo;
9235
9236                 if (arginfo [i].prop)
9237                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9238                 else {
9239                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9240                         if (!mono_error_ok (&error))
9241                                 goto leave;
9242                 }
9243
9244                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9245                 namedarg = create_cattr_named_arg (minfo, typedarg);
9246
9247                 mono_array_setref (namedargs, i, namedarg);
9248         }
9249
9250         *ctor_args = typedargs;
9251         *named_args = namedargs;
9252 leave:
9253         g_free (arginfo);
9254         mono_error_raise_exception (&error);
9255
9256 }
9257
9258 static MonoObject*
9259 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9260 {
9261         static MonoMethod *ctor;
9262
9263         MonoError error;
9264         MonoDomain *domain;
9265         MonoObject *attr;
9266         void *params [4];
9267
9268         g_assert (image->assembly);
9269
9270         if (!ctor)
9271                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9272
9273         domain = mono_domain_get ();
9274         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, &error);
9275         mono_error_raise_exception (&error); /* FIXME don't raise here */
9276         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, &error);
9277         mono_error_raise_exception (&error); /* FIXME don't raise here */
9278         params [1] = mono_assembly_get_object (domain, image->assembly);
9279         params [2] = (gpointer)&cattr->data;
9280         params [3] = &cattr->data_size;
9281         mono_runtime_invoke (ctor, attr, params, NULL);
9282         return attr;
9283 }
9284
9285 static MonoArray*
9286 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9287 {
9288         MonoArray *result;
9289         MonoObject *attr;
9290         int i, n;
9291
9292         mono_error_init (error);
9293
9294         n = 0;
9295         for (i = 0; i < cinfo->num_attrs; ++i) {
9296                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9297                         n ++;
9298         }
9299
9300         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9301         n = 0;
9302         for (i = 0; i < cinfo->num_attrs; ++i) {
9303                 if (!cinfo->attrs [i].ctor)
9304                         /* The cattr type is not finished yet */
9305                         /* We should include the type name but cinfo doesn't contain it */
9306                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9307                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9308                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9309                         if (!mono_error_ok (error))
9310                                 return result;
9311                         mono_array_setref (result, n, attr);
9312                         n ++;
9313                 }
9314         }
9315         return result;
9316 }
9317
9318 MonoArray*
9319 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9320 {
9321         MonoError error;
9322         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9323         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9324
9325         return result;
9326 }
9327
9328 static MonoArray*
9329 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9330 {
9331         MonoArray *result;
9332         MonoObject *attr;
9333         int i;
9334         
9335         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9336         for (i = 0; i < cinfo->num_attrs; ++i) {
9337                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9338                 mono_array_setref (result, i, attr);
9339         }
9340         return result;
9341 }
9342
9343 /**
9344  * mono_custom_attrs_from_index:
9345  *
9346  * Returns: NULL if no attributes are found or if a loading error occurs.
9347  */
9348 MonoCustomAttrInfo*
9349 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9350 {
9351         guint32 mtoken, i, len;
9352         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9353         MonoTableInfo *ca;
9354         MonoCustomAttrInfo *ainfo;
9355         GList *tmp, *list = NULL;
9356         const char *data;
9357         MonoCustomAttrEntry* attr;
9358
9359         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9360
9361         i = mono_metadata_custom_attrs_from_index (image, idx);
9362         if (!i)
9363                 return NULL;
9364         i --;
9365         while (i < ca->rows) {
9366                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9367                         break;
9368                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9369                 ++i;
9370         }
9371         len = g_list_length (list);
9372         if (!len)
9373                 return NULL;
9374         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9375         ainfo->num_attrs = len;
9376         ainfo->image = image;
9377         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9378                 MonoError error;
9379                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9380                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9381                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9382                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9383                         mtoken |= MONO_TOKEN_METHOD_DEF;
9384                         break;
9385                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9386                         mtoken |= MONO_TOKEN_MEMBER_REF;
9387                         break;
9388                 default:
9389                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9390                         break;
9391                 }
9392                 attr = &ainfo->attrs [i - 1];
9393                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9394                 if (!attr->ctor) {
9395                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9396                         mono_loader_set_error_from_mono_error (&error);
9397                         g_list_free (list);
9398                         g_free (ainfo);
9399                         return NULL;
9400                 }
9401
9402                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9403                         /*FIXME raising an exception here doesn't make any sense*/
9404                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9405                         g_list_free (list);
9406                         g_free (ainfo);
9407                         return NULL;
9408                 }
9409                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9410                 attr->data_size = mono_metadata_decode_value (data, &data);
9411                 attr->data = (guchar*)data;
9412         }
9413         g_list_free (list);
9414
9415         return ainfo;
9416 }
9417
9418 MonoCustomAttrInfo*
9419 mono_custom_attrs_from_method (MonoMethod *method)
9420 {
9421         guint32 idx;
9422
9423         /*
9424          * An instantiated method has the same cattrs as the generic method definition.
9425          *
9426          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9427          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9428          */
9429         if (method->is_inflated)
9430                 method = ((MonoMethodInflated *) method)->declaring;
9431         
9432         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9433                 return lookup_custom_attr (method->klass->image, method);
9434
9435         if (!method->token)
9436                 /* Synthetic methods */
9437                 return NULL;
9438
9439         idx = mono_method_get_index (method);
9440         idx <<= MONO_CUSTOM_ATTR_BITS;
9441         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9442         return mono_custom_attrs_from_index (method->klass->image, idx);
9443 }
9444
9445 MonoCustomAttrInfo*
9446 mono_custom_attrs_from_class (MonoClass *klass)
9447 {
9448         guint32 idx;
9449
9450         if (klass->generic_class)
9451                 klass = klass->generic_class->container_class;
9452
9453         if (image_is_dynamic (klass->image))
9454                 return lookup_custom_attr (klass->image, klass);
9455
9456         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9457                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9458                 idx <<= MONO_CUSTOM_ATTR_BITS;
9459                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9460         } else {
9461                 idx = mono_metadata_token_index (klass->type_token);
9462                 idx <<= MONO_CUSTOM_ATTR_BITS;
9463                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9464         }
9465         return mono_custom_attrs_from_index (klass->image, idx);
9466 }
9467
9468 MonoCustomAttrInfo*
9469 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9470 {
9471         guint32 idx;
9472         
9473         if (image_is_dynamic (assembly->image))
9474                 return lookup_custom_attr (assembly->image, assembly);
9475         idx = 1; /* there is only one assembly */
9476         idx <<= MONO_CUSTOM_ATTR_BITS;
9477         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9478         return mono_custom_attrs_from_index (assembly->image, idx);
9479 }
9480
9481 static MonoCustomAttrInfo*
9482 mono_custom_attrs_from_module (MonoImage *image)
9483 {
9484         guint32 idx;
9485         
9486         if (image_is_dynamic (image))
9487                 return lookup_custom_attr (image, image);
9488         idx = 1; /* there is only one module */
9489         idx <<= MONO_CUSTOM_ATTR_BITS;
9490         idx |= MONO_CUSTOM_ATTR_MODULE;
9491         return mono_custom_attrs_from_index (image, idx);
9492 }
9493
9494 MonoCustomAttrInfo*
9495 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9496 {
9497         guint32 idx;
9498         
9499         if (image_is_dynamic (klass->image)) {
9500                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9501                 return lookup_custom_attr (klass->image, property);
9502         }
9503         idx = find_property_index (klass, property);
9504         idx <<= MONO_CUSTOM_ATTR_BITS;
9505         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9506         return mono_custom_attrs_from_index (klass->image, idx);
9507 }
9508
9509 MonoCustomAttrInfo*
9510 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9511 {
9512         guint32 idx;
9513         
9514         if (image_is_dynamic (klass->image)) {
9515                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9516                 return lookup_custom_attr (klass->image, event);
9517         }
9518         idx = find_event_index (klass, event);
9519         idx <<= MONO_CUSTOM_ATTR_BITS;
9520         idx |= MONO_CUSTOM_ATTR_EVENT;
9521         return mono_custom_attrs_from_index (klass->image, idx);
9522 }
9523
9524 MonoCustomAttrInfo*
9525 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9526 {
9527         guint32 idx;
9528         if (image_is_dynamic (klass->image)) {
9529                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9530                 return lookup_custom_attr (klass->image, field);
9531         }
9532         idx = find_field_index (klass, field);
9533         idx <<= MONO_CUSTOM_ATTR_BITS;
9534         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9535         return mono_custom_attrs_from_index (klass->image, idx);
9536 }
9537
9538 /**
9539  * mono_custom_attrs_from_param:
9540  * @method: handle to the method that we want to retrieve custom parameter information from
9541  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9542  *
9543  * The result must be released with mono_custom_attrs_free().
9544  *
9545  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9546  */
9547 MonoCustomAttrInfo*
9548 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9549 {
9550         MonoTableInfo *ca;
9551         guint32 i, idx, method_index;
9552         guint32 param_list, param_last, param_pos, found;
9553         MonoImage *image;
9554         MonoReflectionMethodAux *aux;
9555
9556         /*
9557          * An instantiated method has the same cattrs as the generic method definition.
9558          *
9559          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9560          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9561          */
9562         if (method->is_inflated)
9563                 method = ((MonoMethodInflated *) method)->declaring;
9564
9565         if (image_is_dynamic (method->klass->image)) {
9566                 MonoCustomAttrInfo *res, *ainfo;
9567                 int size;
9568
9569                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9570                 if (!aux || !aux->param_cattr)
9571                         return NULL;
9572
9573                 /* Need to copy since it will be freed later */
9574                 ainfo = aux->param_cattr [param];
9575                 if (!ainfo)
9576                         return NULL;
9577                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9578                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9579                 memcpy (res, ainfo, size);
9580                 return res;
9581         }
9582
9583         image = method->klass->image;
9584         method_index = mono_method_get_index (method);
9585         if (!method_index)
9586                 return NULL;
9587         ca = &image->tables [MONO_TABLE_METHOD];
9588
9589         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9590         if (method_index == ca->rows) {
9591                 ca = &image->tables [MONO_TABLE_PARAM];
9592                 param_last = ca->rows + 1;
9593         } else {
9594                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9595                 ca = &image->tables [MONO_TABLE_PARAM];
9596         }
9597         found = FALSE;
9598         for (i = param_list; i < param_last; ++i) {
9599                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9600                 if (param_pos == param) {
9601                         found = TRUE;
9602                         break;
9603                 }
9604         }
9605         if (!found)
9606                 return NULL;
9607         idx = i;
9608         idx <<= MONO_CUSTOM_ATTR_BITS;
9609         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9610         return mono_custom_attrs_from_index (image, idx);
9611 }
9612
9613 gboolean
9614 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9615 {
9616         int i;
9617         MonoClass *klass;
9618         for (i = 0; i < ainfo->num_attrs; ++i) {
9619                 klass = ainfo->attrs [i].ctor->klass;
9620                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9621                         return TRUE;
9622         }
9623         return FALSE;
9624 }
9625
9626 MonoObject*
9627 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9628 {
9629         MonoError error;
9630         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9631         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9632         return res;
9633 }
9634
9635 MonoObject*
9636 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9637 {
9638         int i, attr_index;
9639         MonoClass *klass;
9640         MonoArray *attrs;
9641
9642         mono_error_init (error);
9643
9644         attr_index = -1;
9645         for (i = 0; i < ainfo->num_attrs; ++i) {
9646                 klass = ainfo->attrs [i].ctor->klass;
9647                 if (mono_class_has_parent (klass, attr_klass)) {
9648                         attr_index = i;
9649                         break;
9650                 }
9651         }
9652         if (attr_index == -1)
9653                 return NULL;
9654
9655         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9656         if (!mono_error_ok (error))
9657                 return NULL;
9658         return mono_array_get (attrs, MonoObject*, attr_index);
9659 }
9660
9661 /*
9662  * mono_reflection_get_custom_attrs_info:
9663  * @obj: a reflection object handle
9664  *
9665  * Return the custom attribute info for attributes defined for the
9666  * reflection handle @obj. The objects.
9667  *
9668  * FIXME this function leaks like a sieve for SRE objects.
9669  */
9670 MonoCustomAttrInfo*
9671 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9672 {
9673         MonoClass *klass;
9674         MonoCustomAttrInfo *cinfo = NULL;
9675         
9676         klass = obj->vtable->klass;
9677         if (klass == mono_defaults.monotype_class) {
9678                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9679                 klass = mono_class_from_mono_type (type);
9680                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9681                 cinfo = mono_custom_attrs_from_class (klass);
9682         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9683                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9684                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9685         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9686                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9687                 cinfo = mono_custom_attrs_from_module (module->image);
9688         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9689                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9690                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9691         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9692                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9693                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9694         } else if (strcmp ("MonoField", klass->name) == 0) {
9695                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9696                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9697         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9698                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9699                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9700         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9701                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9702                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9703         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9704                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9705                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9706                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9707                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9708                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9709                 } else if (is_sr_mono_property (member_class)) {
9710                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9711                         MonoMethod *method;
9712                         if (!(method = prop->property->get))
9713                                 method = prop->property->set;
9714                         g_assert (method);
9715
9716                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9717                 } 
9718 #ifndef DISABLE_REFLECTION_EMIT
9719                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9720                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9721                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9722                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9723                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9724                         MonoMethod *method = NULL;
9725                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9726                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9727                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9728                                 method = ((MonoReflectionMethod *)c->cb)->method;
9729                         else
9730                                 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));
9731
9732                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9733                 } 
9734 #endif
9735                 else {
9736                         char *type_name = mono_type_get_full_name (member_class);
9737                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9738                         MonoException *ex = mono_get_exception_not_supported  (msg);
9739                         g_free (type_name);
9740                         g_free (msg);
9741                         mono_raise_exception (ex);
9742                 }
9743         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9744                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9745                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9746         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9747                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9748                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9749         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9750                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9751                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9752         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9753                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9754                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9755         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9756                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9757                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9758         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9759                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9760                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9761         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9762                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9763                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9764         } else { /* handle other types here... */
9765                 g_error ("get custom attrs not yet supported for %s", klass->name);
9766         }
9767
9768         return cinfo;
9769 }
9770
9771 /*
9772  * mono_reflection_get_custom_attrs_by_type:
9773  * @obj: a reflection object handle
9774  *
9775  * Return an array with all the custom attributes defined of the
9776  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9777  * of that type are returned. The objects are fully build. Return NULL if a loading error
9778  * occurs.
9779  */
9780 MonoArray*
9781 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9782 {
9783         MonoArray *result;
9784         MonoCustomAttrInfo *cinfo;
9785
9786         mono_error_init (error);
9787
9788         cinfo = mono_reflection_get_custom_attrs_info (obj);
9789         if (cinfo) {
9790                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9791                 if (!cinfo->cached)
9792                         mono_custom_attrs_free (cinfo);
9793         } else {
9794                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9795                 if (mono_loader_get_last_error ())
9796                         return NULL;
9797                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9798         }
9799
9800         return result;
9801 }
9802
9803 /*
9804  * mono_reflection_get_custom_attrs:
9805  * @obj: a reflection object handle
9806  *
9807  * Return an array with all the custom attributes defined of the
9808  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9809  * occurs.
9810  */
9811 MonoArray*
9812 mono_reflection_get_custom_attrs (MonoObject *obj)
9813 {
9814         MonoError error;
9815
9816         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9817 }
9818
9819 /*
9820  * mono_reflection_get_custom_attrs_data:
9821  * @obj: a reflection obj handle
9822  *
9823  * Returns an array of System.Reflection.CustomAttributeData,
9824  * which include information about attributes reflected on
9825  * types loaded using the Reflection Only methods
9826  */
9827 MonoArray*
9828 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9829 {
9830         MonoArray *result;
9831         MonoCustomAttrInfo *cinfo;
9832
9833         cinfo = mono_reflection_get_custom_attrs_info (obj);
9834         if (cinfo) {
9835                 result = mono_custom_attrs_data_construct (cinfo);
9836                 if (!cinfo->cached)
9837                         mono_custom_attrs_free (cinfo);
9838         } else
9839                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9840
9841         return result;
9842 }
9843
9844 static MonoReflectionType*
9845 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9846 {
9847         static MonoMethod *method_get_underlying_system_type = NULL;
9848         MonoMethod *usertype_method;
9849
9850         if (!method_get_underlying_system_type)
9851                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9852         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9853         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9854 }
9855
9856
9857 static gboolean
9858 is_corlib_type (MonoClass *klass)
9859 {
9860         return klass->image == mono_defaults.corlib;
9861 }
9862
9863 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9864         static MonoClass *cached_class; \
9865         if (cached_class) \
9866                 return cached_class == _class; \
9867         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9868                 cached_class = _class; \
9869                 return TRUE; \
9870         } \
9871         return FALSE; \
9872 } while (0) \
9873
9874
9875 #ifndef DISABLE_REFLECTION_EMIT
9876 static gboolean
9877 is_sre_array (MonoClass *klass)
9878 {
9879         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9880 }
9881
9882 static gboolean
9883 is_sre_byref (MonoClass *klass)
9884 {
9885         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9886 }
9887
9888 static gboolean
9889 is_sre_pointer (MonoClass *klass)
9890 {
9891         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9892 }
9893
9894 static gboolean
9895 is_sre_generic_instance (MonoClass *klass)
9896 {
9897         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9898 }
9899
9900 static gboolean
9901 is_sre_type_builder (MonoClass *klass)
9902 {
9903         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9904 }
9905
9906 static gboolean
9907 is_sre_method_builder (MonoClass *klass)
9908 {
9909         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9910 }
9911
9912 static gboolean
9913 is_sre_ctor_builder (MonoClass *klass)
9914 {
9915         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9916 }
9917
9918 static gboolean
9919 is_sre_field_builder (MonoClass *klass)
9920 {
9921         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9922 }
9923
9924 static gboolean
9925 is_sre_method_on_tb_inst (MonoClass *klass)
9926 {
9927         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9928 }
9929
9930 static gboolean
9931 is_sre_ctor_on_tb_inst (MonoClass *klass)
9932 {
9933         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9934 }
9935
9936 MonoType*
9937 mono_reflection_type_get_handle (MonoReflectionType* ref)
9938 {
9939         MonoClass *klass;
9940         if (!ref)
9941                 return NULL;
9942         if (ref->type)
9943                 return ref->type;
9944
9945         if (is_usertype (ref)) {
9946                 ref = mono_reflection_type_get_underlying_system_type (ref);
9947                 if (ref == NULL || is_usertype (ref))
9948                         return NULL;
9949                 if (ref->type)
9950                         return ref->type;
9951         }
9952
9953         klass = mono_object_class (ref);
9954
9955         if (is_sre_array (klass)) {
9956                 MonoType *res;
9957                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9958                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9959                 g_assert (base);
9960                 if (sre_array->rank == 0) //single dimentional array
9961                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9962                 else
9963                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9964                 sre_array->type.type = res;
9965                 return res;
9966         } else if (is_sre_byref (klass)) {
9967                 MonoType *res;
9968                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9969                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9970                 g_assert (base);
9971                 res = &mono_class_from_mono_type (base)->this_arg;
9972                 sre_byref->type.type = res;
9973                 return res;
9974         } else if (is_sre_pointer (klass)) {
9975                 MonoType *res;
9976                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9977                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9978                 g_assert (base);
9979                 res = &mono_ptr_class_get (base)->byval_arg;
9980                 sre_pointer->type.type = res;
9981                 return res;
9982         } else if (is_sre_generic_instance (klass)) {
9983                 MonoType *res, **types;
9984                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9985                 int i, count;
9986
9987                 count = mono_array_length (gclass->type_arguments);
9988                 types = g_new0 (MonoType*, count);
9989                 for (i = 0; i < count; ++i) {
9990                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9991                         types [i] = mono_reflection_type_get_handle (t);
9992                         if (!types[i]) {
9993                                 g_free (types);
9994                                 return NULL;
9995                         }
9996                 }
9997
9998                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9999                 g_free (types);
10000                 g_assert (res);
10001                 gclass->type.type = res;
10002                 return res;
10003         }
10004
10005         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10006         return NULL;
10007 }
10008
10009
10010
10011 void
10012 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10013 {
10014         mono_reflection_type_get_handle (type);
10015 }
10016
10017 void
10018 mono_reflection_register_with_runtime (MonoReflectionType *type)
10019 {
10020         MonoType *res = mono_reflection_type_get_handle (type);
10021         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10022         MonoClass *klass;
10023
10024         if (!res)
10025                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10026
10027         klass = mono_class_from_mono_type (res);
10028
10029         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10030         mono_domain_lock (domain);
10031
10032         if (!image_is_dynamic (klass->image)) {
10033                 mono_class_setup_supertypes (klass);
10034         } else {
10035                 if (!domain->type_hash)
10036                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10037                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10038                 mono_g_hash_table_insert (domain->type_hash, res, type);
10039         }
10040         mono_domain_unlock (domain);
10041         mono_loader_unlock ();
10042 }
10043
10044 /**
10045  * LOCKING: Assumes the loader lock is held.
10046  */
10047 static MonoMethodSignature*
10048 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10049         MonoMethodSignature *sig;
10050         int count, i;
10051
10052         count = parameters? mono_array_length (parameters): 0;
10053
10054         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10055         sig->param_count = count;
10056         sig->sentinelpos = -1; /* FIXME */
10057         for (i = 0; i < count; ++i)
10058                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10059         return sig;
10060 }
10061
10062 /**
10063  * LOCKING: Assumes the loader lock is held.
10064  */
10065 static MonoMethodSignature*
10066 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10067         MonoMethodSignature *sig;
10068
10069         sig = parameters_to_signature (image, ctor->parameters);
10070         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10071         sig->ret = &mono_defaults.void_class->byval_arg;
10072         return sig;
10073 }
10074
10075 /**
10076  * LOCKING: Assumes the loader lock is held.
10077  */
10078 static MonoMethodSignature*
10079 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10080         MonoMethodSignature *sig;
10081
10082         sig = parameters_to_signature (image, method->parameters);
10083         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10084         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10085         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10086         return sig;
10087 }
10088
10089 static MonoMethodSignature*
10090 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10091         MonoMethodSignature *sig;
10092
10093         sig = parameters_to_signature (NULL, method->parameters);
10094         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10095         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10096         sig->generic_param_count = 0;
10097         return sig;
10098 }
10099
10100 static void
10101 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10102 {
10103         MonoClass *klass = mono_object_class (prop);
10104         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10105                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10106                 *name = mono_string_to_utf8 (pb->name);
10107                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10108         } else {
10109                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10110                 *name = g_strdup (p->property->name);
10111                 if (p->property->get)
10112                         *type = mono_method_signature (p->property->get)->ret;
10113                 else
10114                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10115         }
10116 }
10117
10118 static void
10119 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10120 {
10121         MonoClass *klass = mono_object_class (field);
10122         if (strcmp (klass->name, "FieldBuilder") == 0) {
10123                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10124                 *name = mono_string_to_utf8 (fb->name);
10125                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10126         } else {
10127                 MonoReflectionField *f = (MonoReflectionField *)field;
10128                 *name = g_strdup (mono_field_get_name (f->field));
10129                 *type = f->field->type;
10130         }
10131 }
10132
10133 #else /* DISABLE_REFLECTION_EMIT */
10134
10135 void
10136 mono_reflection_register_with_runtime (MonoReflectionType *type)
10137 {
10138         /* This is empty */
10139 }
10140
10141 static gboolean
10142 is_sre_type_builder (MonoClass *klass)
10143 {
10144         return FALSE;
10145 }
10146
10147 static gboolean
10148 is_sre_generic_instance (MonoClass *klass)
10149 {
10150         return FALSE;
10151 }
10152
10153 static void
10154 init_type_builder_generics (MonoObject *type)
10155 {
10156 }
10157
10158 #endif /* !DISABLE_REFLECTION_EMIT */
10159
10160
10161 static gboolean
10162 is_sr_mono_field (MonoClass *klass)
10163 {
10164         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10165 }
10166
10167 static gboolean
10168 is_sr_mono_property (MonoClass *klass)
10169 {
10170         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10171 }
10172
10173 static gboolean
10174 is_sr_mono_method (MonoClass *klass)
10175 {
10176         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10177 }
10178
10179 static gboolean
10180 is_sr_mono_cmethod (MonoClass *klass)
10181 {
10182         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10183 }
10184
10185 static gboolean
10186 is_sr_mono_generic_method (MonoClass *klass)
10187 {
10188         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10189 }
10190
10191 static gboolean
10192 is_sr_mono_generic_cmethod (MonoClass *klass)
10193 {
10194         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10195 }
10196
10197 gboolean
10198 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10199 {
10200         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10201 }
10202
10203 static gboolean
10204 is_usertype (MonoReflectionType *ref)
10205 {
10206         MonoClass *klass = mono_object_class (ref);
10207         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10208 }
10209
10210 static MonoReflectionType*
10211 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10212 {
10213         mono_error_init (error);
10214         if (!type || type->type)
10215                 return type;
10216
10217         if (is_usertype (type)) {
10218                 type = mono_reflection_type_get_underlying_system_type (type);
10219                 if (is_usertype (type)) {
10220                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10221                         return NULL;
10222                 }
10223         }
10224
10225         return type;
10226 }
10227 /*
10228  * Encode a value in a custom attribute stream of bytes.
10229  * The value to encode is either supplied as an object in argument val
10230  * (valuetypes are boxed), or as a pointer to the data in the
10231  * argument argval.
10232  * @type represents the type of the value
10233  * @buffer is the start of the buffer
10234  * @p the current position in the buffer
10235  * @buflen contains the size of the buffer and is used to return the new buffer size
10236  * if this needs to be realloced.
10237  * @retbuffer and @retp return the start and the position of the buffer
10238  */
10239 static void
10240 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10241 {
10242         MonoTypeEnum simple_type;
10243         
10244         if ((p-buffer) + 10 >= *buflen) {
10245                 char *newbuf;
10246                 *buflen *= 2;
10247                 newbuf = (char *)g_realloc (buffer, *buflen);
10248                 p = newbuf + (p-buffer);
10249                 buffer = newbuf;
10250         }
10251         if (!argval)
10252                 argval = ((char*)arg + sizeof (MonoObject));
10253         simple_type = type->type;
10254 handle_enum:
10255         switch (simple_type) {
10256         case MONO_TYPE_BOOLEAN:
10257         case MONO_TYPE_U1:
10258         case MONO_TYPE_I1:
10259                 *p++ = *argval;
10260                 break;
10261         case MONO_TYPE_CHAR:
10262         case MONO_TYPE_U2:
10263         case MONO_TYPE_I2:
10264                 swap_with_size (p, argval, 2, 1);
10265                 p += 2;
10266                 break;
10267         case MONO_TYPE_U4:
10268         case MONO_TYPE_I4:
10269         case MONO_TYPE_R4:
10270                 swap_with_size (p, argval, 4, 1);
10271                 p += 4;
10272                 break;
10273         case MONO_TYPE_R8:
10274                 swap_with_size (p, argval, 8, 1);
10275                 p += 8;
10276                 break;
10277         case MONO_TYPE_U8:
10278         case MONO_TYPE_I8:
10279                 swap_with_size (p, argval, 8, 1);
10280                 p += 8;
10281                 break;
10282         case MONO_TYPE_VALUETYPE:
10283                 if (type->data.klass->enumtype) {
10284                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10285                         goto handle_enum;
10286                 } else {
10287                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10288                 }
10289                 break;
10290         case MONO_TYPE_STRING: {
10291                 char *str;
10292                 guint32 slen;
10293                 if (!arg) {
10294                         *p++ = 0xFF;
10295                         break;
10296                 }
10297                 str = mono_string_to_utf8 ((MonoString*)arg);
10298                 slen = strlen (str);
10299                 if ((p-buffer) + 10 + slen >= *buflen) {
10300                         char *newbuf;
10301                         *buflen *= 2;
10302                         *buflen += slen;
10303                         newbuf = (char *)g_realloc (buffer, *buflen);
10304                         p = newbuf + (p-buffer);
10305                         buffer = newbuf;
10306                 }
10307                 mono_metadata_encode_value (slen, p, &p);
10308                 memcpy (p, str, slen);
10309                 p += slen;
10310                 g_free (str);
10311                 break;
10312         }
10313         case MONO_TYPE_CLASS: {
10314                 char *str;
10315                 guint32 slen;
10316                 if (!arg) {
10317                         *p++ = 0xFF;
10318                         break;
10319                 }
10320 handle_type:
10321                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10322                 slen = strlen (str);
10323                 if ((p-buffer) + 10 + slen >= *buflen) {
10324                         char *newbuf;
10325                         *buflen *= 2;
10326                         *buflen += slen;
10327                         newbuf = (char *)g_realloc (buffer, *buflen);
10328                         p = newbuf + (p-buffer);
10329                         buffer = newbuf;
10330                 }
10331                 mono_metadata_encode_value (slen, p, &p);
10332                 memcpy (p, str, slen);
10333                 p += slen;
10334                 g_free (str);
10335                 break;
10336         }
10337         case MONO_TYPE_SZARRAY: {
10338                 int len, i;
10339                 MonoClass *eclass, *arg_eclass;
10340
10341                 if (!arg) {
10342                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10343                         break;
10344                 }
10345                 len = mono_array_length ((MonoArray*)arg);
10346                 *p++ = len & 0xff;
10347                 *p++ = (len >> 8) & 0xff;
10348                 *p++ = (len >> 16) & 0xff;
10349                 *p++ = (len >> 24) & 0xff;
10350                 *retp = p;
10351                 *retbuffer = buffer;
10352                 eclass = type->data.klass;
10353                 arg_eclass = mono_object_class (arg)->element_class;
10354
10355                 if (!eclass) {
10356                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10357                         eclass = mono_defaults.object_class;
10358                 }
10359                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10360                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10361                         int elsize = mono_class_array_element_size (arg_eclass);
10362                         for (i = 0; i < len; ++i) {
10363                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10364                                 elptr += elsize;
10365                         }
10366                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10367                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10368                         int elsize = mono_class_array_element_size (eclass);
10369                         for (i = 0; i < len; ++i) {
10370                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10371                                 elptr += elsize;
10372                         }
10373                 } else {
10374                         for (i = 0; i < len; ++i) {
10375                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10376                         }
10377                 }
10378                 break;
10379         }
10380         case MONO_TYPE_OBJECT: {
10381                 MonoClass *klass;
10382                 char *str;
10383                 guint32 slen;
10384
10385                 /*
10386                  * The parameter type is 'object' but the type of the actual
10387                  * argument is not. So we have to add type information to the blob
10388                  * too. This is completely undocumented in the spec.
10389                  */
10390
10391                 if (arg == NULL) {
10392                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10393                         *p++ = 0xFF;
10394                         break;
10395                 }
10396                 
10397                 klass = mono_object_class (arg);
10398
10399                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10400                         *p++ = 0x50;
10401                         goto handle_type;
10402                 } else if (klass->enumtype) {
10403                         *p++ = 0x55;
10404                 } else if (klass == mono_defaults.string_class) {
10405                         simple_type = MONO_TYPE_STRING;
10406                         *p++ = 0x0E;
10407                         goto handle_enum;
10408                 } else if (klass->rank == 1) {
10409                         *p++ = 0x1D;
10410                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10411                                 /* See Partition II, Appendix B3 */
10412                                 *p++ = 0x51;
10413                         else
10414                                 *p++ = klass->element_class->byval_arg.type;
10415                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10416                         break;
10417                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10418                         *p++ = simple_type = klass->byval_arg.type;
10419                         goto handle_enum;
10420                 } else {
10421                         g_error ("unhandled type in custom attr");
10422                 }
10423                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10424                 slen = strlen (str);
10425                 if ((p-buffer) + 10 + slen >= *buflen) {
10426                         char *newbuf;
10427                         *buflen *= 2;
10428                         *buflen += slen;
10429                         newbuf = (char *)g_realloc (buffer, *buflen);
10430                         p = newbuf + (p-buffer);
10431                         buffer = newbuf;
10432                 }
10433                 mono_metadata_encode_value (slen, p, &p);
10434                 memcpy (p, str, slen);
10435                 p += slen;
10436                 g_free (str);
10437                 simple_type = mono_class_enum_basetype (klass)->type;
10438                 goto handle_enum;
10439         }
10440         default:
10441                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10442         }
10443         *retp = p;
10444         *retbuffer = buffer;
10445 }
10446
10447 static void
10448 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10449 {
10450         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10451                 char *str = type_get_qualified_name (type, NULL);
10452                 int slen = strlen (str);
10453
10454                 *p++ = 0x55;
10455                 /*
10456                  * This seems to be optional...
10457                  * *p++ = 0x80;
10458                  */
10459                 mono_metadata_encode_value (slen, p, &p);
10460                 memcpy (p, str, slen);
10461                 p += slen;
10462                 g_free (str);
10463         } else if (type->type == MONO_TYPE_OBJECT) {
10464                 *p++ = 0x51;
10465         } else if (type->type == MONO_TYPE_CLASS) {
10466                 /* it should be a type: encode_cattr_value () has the check */
10467                 *p++ = 0x50;
10468         } else {
10469                 mono_metadata_encode_value (type->type, p, &p);
10470                 if (type->type == MONO_TYPE_SZARRAY)
10471                         /* See the examples in Partition VI, Annex B */
10472                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10473         }
10474
10475         *retp = p;
10476 }
10477
10478 #ifndef DISABLE_REFLECTION_EMIT
10479 static void
10480 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10481 {
10482         int len;
10483         /* Preallocate a large enough buffer */
10484         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10485                 char *str = type_get_qualified_name (type, NULL);
10486                 len = strlen (str);
10487                 g_free (str);
10488         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10489                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10490                 len = strlen (str);
10491                 g_free (str);
10492         } else {
10493                 len = 0;
10494         }
10495         len += strlen (name);
10496
10497         if ((p-buffer) + 20 + len >= *buflen) {
10498                 char *newbuf;
10499                 *buflen *= 2;
10500                 *buflen += len;
10501                 newbuf = (char *)g_realloc (buffer, *buflen);
10502                 p = newbuf + (p-buffer);
10503                 buffer = newbuf;
10504         }
10505
10506         encode_field_or_prop_type (type, p, &p);
10507
10508         len = strlen (name);
10509         mono_metadata_encode_value (len, p, &p);
10510         memcpy (p, name, len);
10511         p += len;
10512         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10513         *retp = p;
10514         *retbuffer = buffer;
10515 }
10516
10517 /*
10518  * mono_reflection_get_custom_attrs_blob:
10519  * @ctor: custom attribute constructor
10520  * @ctorArgs: arguments o the constructor
10521  * @properties:
10522  * @propValues:
10523  * @fields:
10524  * @fieldValues:
10525  * 
10526  * Creates the blob of data that needs to be saved in the metadata and that represents
10527  * the custom attributed described by @ctor, @ctorArgs etc.
10528  * Returns: a Byte array representing the blob of data.
10529  */
10530 MonoArray*
10531 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10532 {
10533         MonoArray *result;
10534         MonoMethodSignature *sig;
10535         MonoObject *arg;
10536         char *buffer, *p;
10537         guint32 buflen, i;
10538
10539         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10540                 /* sig is freed later so allocate it in the heap */
10541                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10542         } else {
10543                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10544         }
10545
10546         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10547         buflen = 256;
10548         p = buffer = (char *)g_malloc (buflen);
10549         /* write the prolog */
10550         *p++ = 1;
10551         *p++ = 0;
10552         for (i = 0; i < sig->param_count; ++i) {
10553                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10554                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10555         }
10556         i = 0;
10557         if (properties)
10558                 i += mono_array_length (properties);
10559         if (fields)
10560                 i += mono_array_length (fields);
10561         *p++ = i & 0xff;
10562         *p++ = (i >> 8) & 0xff;
10563         if (properties) {
10564                 MonoObject *prop;
10565                 for (i = 0; i < mono_array_length (properties); ++i) {
10566                         MonoType *ptype;
10567                         char *pname;
10568
10569                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10570                         get_prop_name_and_type (prop, &pname, &ptype);
10571                         *p++ = 0x54; /* PROPERTY signature */
10572                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10573                         g_free (pname);
10574                 }
10575         }
10576
10577         if (fields) {
10578                 MonoObject *field;
10579                 for (i = 0; i < mono_array_length (fields); ++i) {
10580                         MonoType *ftype;
10581                         char *fname;
10582
10583                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10584                         get_field_name_and_type (field, &fname, &ftype);
10585                         *p++ = 0x53; /* FIELD signature */
10586                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10587                         g_free (fname);
10588                 }
10589         }
10590
10591         g_assert (p - buffer <= buflen);
10592         buflen = p - buffer;
10593         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10594         p = mono_array_addr (result, char, 0);
10595         memcpy (p, buffer, buflen);
10596         g_free (buffer);
10597         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10598                 g_free (sig);
10599         return result;
10600 }
10601
10602 /*
10603  * mono_reflection_setup_internal_class:
10604  * @tb: a TypeBuilder object
10605  *
10606  * Creates a MonoClass that represents the TypeBuilder.
10607  * This is a trick that lets us simplify a lot of reflection code
10608  * (and will allow us to support Build and Run assemblies easier).
10609  */
10610 void
10611 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10612 {
10613         MonoError error;
10614         MonoClass *klass, *parent;
10615
10616         RESOLVE_TYPE (tb->parent, &error);
10617         mono_error_raise_exception (&error); /* FIXME don't raise here */
10618
10619         mono_loader_lock ();
10620
10621         if (tb->parent) {
10622                 /* check so we can compile corlib correctly */
10623                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10624                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10625                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10626                 } else {
10627                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10628                 }
10629         } else {
10630                 parent = NULL;
10631         }
10632         
10633         /* the type has already being created: it means we just have to change the parent */
10634         if (tb->type.type) {
10635                 klass = mono_class_from_mono_type (tb->type.type);
10636                 klass->parent = NULL;
10637                 /* fool mono_class_setup_parent */
10638                 klass->supertypes = NULL;
10639                 mono_class_setup_parent (klass, parent);
10640                 mono_class_setup_mono_type (klass);
10641                 mono_loader_unlock ();
10642                 return;
10643         }
10644
10645         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10646
10647         klass->image = &tb->module->dynamic_image->image;
10648
10649         klass->inited = 1; /* we lie to the runtime */
10650         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10651         if (!mono_error_ok (&error))
10652                 goto failure;
10653         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10654         if (!mono_error_ok (&error))
10655                 goto failure;
10656         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10657         klass->flags = tb->attrs;
10658         
10659         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10660
10661         klass->element_class = klass;
10662
10663         if (mono_class_get_ref_info (klass) == NULL) {
10664
10665                 mono_class_set_ref_info (klass, tb);
10666
10667                 /* Put into cache so mono_class_get_checked () will find it.
10668                 Skip nested types as those should not be available on the global scope. */
10669                 if (!tb->nesting_type)
10670                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10671
10672                 /*
10673                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10674                 by performing a mono_class_get which does the full resolution.
10675
10676                 Working around this semantics would require us to write a lot of code for no clear advantage.
10677                 */
10678                 mono_image_append_class_to_reflection_info_set (klass);
10679         } else {
10680                 g_assert (mono_class_get_ref_info (klass) == tb);
10681         }
10682
10683         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10684
10685         if (parent != NULL) {
10686                 mono_class_setup_parent (klass, parent);
10687         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10688                 const char *old_n = klass->name;
10689                 /* trick to get relative numbering right when compiling corlib */
10690                 klass->name = "BuildingObject";
10691                 mono_class_setup_parent (klass, mono_defaults.object_class);
10692                 klass->name = old_n;
10693         }
10694
10695         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10696                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10697                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10698                 klass->instance_size = sizeof (MonoObject);
10699                 klass->size_inited = 1;
10700                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10701         }
10702
10703         mono_class_setup_mono_type (klass);
10704
10705         mono_class_setup_supertypes (klass);
10706
10707         /*
10708          * FIXME: handle interfaces.
10709          */
10710
10711         tb->type.type = &klass->byval_arg;
10712
10713         if (tb->nesting_type) {
10714                 g_assert (tb->nesting_type->type);
10715                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10716         }
10717
10718         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10719
10720         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10721         
10722         mono_loader_unlock ();
10723         return;
10724
10725 failure:
10726         mono_loader_unlock ();
10727         mono_error_raise_exception (&error);
10728 }
10729
10730 /*
10731  * mono_reflection_setup_generic_class:
10732  * @tb: a TypeBuilder object
10733  *
10734  * Setup the generic class before adding the first generic parameter.
10735  */
10736 void
10737 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10738 {
10739 }
10740
10741 /*
10742  * mono_reflection_create_generic_class:
10743  * @tb: a TypeBuilder object
10744  *
10745  * Creates the generic class after all generic parameters have been added.
10746  */
10747 void
10748 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10749 {
10750         MonoClass *klass;
10751         int count, i;
10752
10753         klass = mono_class_from_mono_type (tb->type.type);
10754
10755         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10756
10757         if (klass->generic_container || (count == 0))
10758                 return;
10759
10760         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10761
10762         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10763
10764         klass->generic_container->owner.klass = klass;
10765         klass->generic_container->type_argc = count;
10766         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10767
10768         klass->is_generic = 1;
10769
10770         for (i = 0; i < count; i++) {
10771                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10772                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10773                 klass->generic_container->type_params [i] = *param;
10774                 /*Make sure we are a diferent type instance */
10775                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10776                 klass->generic_container->type_params [i].info.pklass = NULL;
10777                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10778
10779                 g_assert (klass->generic_container->type_params [i].param.owner);
10780         }
10781
10782         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10783 }
10784
10785 /*
10786  * mono_reflection_create_internal_class:
10787  * @tb: a TypeBuilder object
10788  *
10789  * Actually create the MonoClass that is associated with the TypeBuilder.
10790  */
10791 void
10792 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10793 {
10794         MonoClass *klass;
10795
10796         klass = mono_class_from_mono_type (tb->type.type);
10797
10798         mono_loader_lock ();
10799         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10800                 MonoReflectionFieldBuilder *fb;
10801                 MonoClass *ec;
10802                 MonoType *enum_basetype;
10803
10804                 g_assert (tb->fields != NULL);
10805                 g_assert (mono_array_length (tb->fields) >= 1);
10806
10807                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10808
10809                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10810                         mono_loader_unlock ();
10811                         return;
10812                 }
10813
10814                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10815                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10816                 if (!klass->element_class)
10817                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10818
10819                 /*
10820                  * get the element_class from the current corlib.
10821                  */
10822                 ec = default_class_from_mono_type (enum_basetype);
10823                 klass->instance_size = ec->instance_size;
10824                 klass->size_inited = 1;
10825                 /* 
10826                  * this is almost safe to do with enums and it's needed to be able
10827                  * to create objects of the enum type (for use in SetConstant).
10828                  */
10829                 /* FIXME: Does this mean enums can't have method overrides ? */
10830                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10831         }
10832         mono_loader_unlock ();
10833 }
10834
10835 static MonoMarshalSpec*
10836 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10837                                                                 MonoReflectionMarshal *minfo)
10838 {
10839         MonoMarshalSpec *res;
10840
10841         res = image_g_new0 (image, MonoMarshalSpec, 1);
10842         res->native = (MonoMarshalNative)minfo->type;
10843
10844         switch (minfo->type) {
10845         case MONO_NATIVE_LPARRAY:
10846                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10847                 if (minfo->has_size) {
10848                         res->data.array_data.param_num = minfo->param_num;
10849                         res->data.array_data.num_elem = minfo->count;
10850                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10851                 }
10852                 else {
10853                         res->data.array_data.param_num = -1;
10854                         res->data.array_data.num_elem = -1;
10855                         res->data.array_data.elem_mult = -1;
10856                 }
10857                 break;
10858
10859         case MONO_NATIVE_BYVALTSTR:
10860         case MONO_NATIVE_BYVALARRAY:
10861                 res->data.array_data.num_elem = minfo->count;
10862                 break;
10863
10864         case MONO_NATIVE_CUSTOM:
10865                 if (minfo->marshaltyperef)
10866                         res->data.custom_data.custom_name =
10867                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10868                 if (minfo->mcookie)
10869                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10870                 break;
10871
10872         default:
10873                 break;
10874         }
10875
10876         return res;
10877 }
10878 #endif /* !DISABLE_REFLECTION_EMIT */
10879
10880 MonoReflectionMarshalAsAttribute*
10881 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10882                                                                                    MonoMarshalSpec *spec)
10883 {
10884         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10885         MonoError error;
10886         MonoReflectionType *rt;
10887         MonoReflectionMarshalAsAttribute *minfo;
10888         MonoType *mtype;
10889
10890         if (!System_Reflection_Emit_MarshalAsAttribute) {
10891                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10892                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10893                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10894         }
10895
10896         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, System_Reflection_Emit_MarshalAsAttribute, &error);
10897         mono_error_raise_exception (&error); /* FIXME don't raise here */
10898         minfo->utype = spec->native;
10899
10900         switch (minfo->utype) {
10901         case MONO_NATIVE_LPARRAY:
10902                 minfo->array_subtype = spec->data.array_data.elem_type;
10903                 minfo->size_const = spec->data.array_data.num_elem;
10904                 if (spec->data.array_data.param_num != -1)
10905                         minfo->size_param_index = spec->data.array_data.param_num;
10906                 break;
10907
10908         case MONO_NATIVE_BYVALTSTR:
10909         case MONO_NATIVE_BYVALARRAY:
10910                 minfo->size_const = spec->data.array_data.num_elem;
10911                 break;
10912
10913         case MONO_NATIVE_CUSTOM:
10914                 if (spec->data.custom_data.custom_name) {
10915                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10916                         if (mtype) {
10917                                 rt = mono_type_get_object_checked (domain, mtype, &error);
10918                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10919
10920                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10921                         }
10922
10923                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10924                 }
10925                 if (spec->data.custom_data.cookie)
10926                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10927                 break;
10928
10929         default:
10930                 break;
10931         }
10932
10933         return minfo;
10934 }
10935
10936 #ifndef DISABLE_REFLECTION_EMIT
10937 static MonoMethod*
10938 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10939                                          ReflectionMethodBuilder *rmb,
10940                                          MonoMethodSignature *sig)
10941 {
10942         MonoError error;
10943         MonoMethod *m;
10944         MonoMethodWrapper *wrapperm;
10945         MonoMarshalSpec **specs;
10946         MonoReflectionMethodAux *method_aux;
10947         MonoImage *image;
10948         gboolean dynamic;
10949         int i;
10950
10951         mono_error_init (&error);
10952         /*
10953          * Methods created using a MethodBuilder should have their memory allocated
10954          * inside the image mempool, while dynamic methods should have their memory
10955          * malloc'd.
10956          */
10957         dynamic = rmb->refs != NULL;
10958         image = dynamic ? NULL : klass->image;
10959
10960         if (!dynamic)
10961                 g_assert (!klass->generic_class);
10962
10963         mono_loader_lock ();
10964
10965         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10966                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10967                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10968         else
10969                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10970
10971         wrapperm = (MonoMethodWrapper*)m;
10972
10973         m->dynamic = dynamic;
10974         m->slot = -1;
10975         m->flags = rmb->attrs;
10976         m->iflags = rmb->iattrs;
10977         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10978         m->klass = klass;
10979         m->signature = sig;
10980         m->sre_method = TRUE;
10981         m->skip_visibility = rmb->skip_visibility;
10982         if (rmb->table_idx)
10983                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10984
10985         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10986                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10987                         m->string_ctor = 1;
10988
10989                 m->signature->pinvoke = 1;
10990         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10991                 m->signature->pinvoke = 1;
10992
10993                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10994
10995                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10996                 g_assert (mono_error_ok (&error));
10997                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10998                 g_assert (mono_error_ok (&error));
10999                 
11000                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11001
11002                 if (image_is_dynamic (klass->image))
11003                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11004
11005                 mono_loader_unlock ();
11006
11007                 return m;
11008         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11009                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11010                 MonoMethodHeader *header;
11011                 guint32 code_size;
11012                 gint32 max_stack, i;
11013                 gint32 num_locals = 0;
11014                 gint32 num_clauses = 0;
11015                 guint8 *code;
11016
11017                 if (rmb->ilgen) {
11018                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11019                         code_size = rmb->ilgen->code_len;
11020                         max_stack = rmb->ilgen->max_stack;
11021                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11022                         if (rmb->ilgen->ex_handlers)
11023                                 num_clauses = method_count_clauses (rmb->ilgen);
11024                 } else {
11025                         if (rmb->code) {
11026                                 code = mono_array_addr (rmb->code, guint8, 0);
11027                                 code_size = mono_array_length (rmb->code);
11028                                 /* we probably need to run a verifier on the code... */
11029                                 max_stack = 8; 
11030                         }
11031                         else {
11032                                 code = NULL;
11033                                 code_size = 0;
11034                                 max_stack = 8;
11035                         }
11036                 }
11037
11038                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11039                 header->code_size = code_size;
11040                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11041                 memcpy ((char*)header->code, code, code_size);
11042                 header->max_stack = max_stack;
11043                 header->init_locals = rmb->init_locals;
11044                 header->num_locals = num_locals;
11045
11046                 for (i = 0; i < num_locals; ++i) {
11047                         MonoReflectionLocalBuilder *lb = 
11048                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11049
11050                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11051                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11052                 }
11053
11054                 header->num_clauses = num_clauses;
11055                 if (num_clauses) {
11056                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11057                                  rmb->ilgen, num_clauses);
11058                 }
11059
11060                 wrapperm->header = header;
11061         }
11062
11063         if (rmb->generic_params) {
11064                 int count = mono_array_length (rmb->generic_params);
11065                 MonoGenericContainer *container = rmb->generic_container;
11066
11067                 g_assert (container);
11068
11069                 container->type_argc = count;
11070                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11071                 container->owner.method = m;
11072                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11073
11074                 m->is_generic = TRUE;
11075                 mono_method_set_generic_container (m, container);
11076
11077                 for (i = 0; i < count; i++) {
11078                         MonoReflectionGenericParam *gp =
11079                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11080                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11081                         container->type_params [i] = *param;
11082                 }
11083
11084                 /*
11085                  * The method signature might have pointers to generic parameters that belong to other methods.
11086                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11087                  * generic parameters.
11088                  */
11089                 for (i = 0; i < m->signature->param_count; ++i) {
11090                         MonoType *t = m->signature->params [i];
11091                         if (t->type == MONO_TYPE_MVAR) {
11092                                 MonoGenericParam *gparam =  t->data.generic_param;
11093                                 if (gparam->num < count) {
11094                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11095                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11096                                 }
11097
11098                         }
11099                 }
11100
11101                 if (klass->generic_container) {
11102                         container->parent = klass->generic_container;
11103                         container->context.class_inst = klass->generic_container->context.class_inst;
11104                 }
11105                 container->context.method_inst = mono_get_shared_generic_inst (container);
11106         }
11107
11108         if (rmb->refs) {
11109                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11110                 int i;
11111                 void **data;
11112
11113                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11114
11115                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11116                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11117                 for (i = 0; i < rmb->nrefs; ++i)
11118                         data [i + 1] = rmb->refs [i];
11119         }
11120
11121         method_aux = NULL;
11122
11123         /* Parameter info */
11124         if (rmb->pinfo) {
11125                 if (!method_aux)
11126                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11127                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11128                 for (i = 0; i <= m->signature->param_count; ++i) {
11129                         MonoReflectionParamBuilder *pb;
11130                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11131                                 if ((i > 0) && (pb->attrs)) {
11132                                         /* Make a copy since it might point to a shared type structure */
11133                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11134                                         m->signature->params [i - 1]->attrs = pb->attrs;
11135                                 }
11136
11137                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11138                                         MonoDynamicImage *assembly;
11139                                         guint32 idx, len;
11140                                         MonoTypeEnum def_type;
11141                                         char *p;
11142                                         const char *p2;
11143
11144                                         if (!method_aux->param_defaults) {
11145                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11146                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11147                                         }
11148                                         assembly = (MonoDynamicImage*)klass->image;
11149                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11150                                         /* Copy the data from the blob since it might get realloc-ed */
11151                                         p = assembly->blob.data + idx;
11152                                         len = mono_metadata_decode_blob_size (p, &p2);
11153                                         len += p2 - p;
11154                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11155                                         method_aux->param_default_types [i] = def_type;
11156                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11157                                 }
11158
11159                                 if (pb->name) {
11160                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11161                                         g_assert (mono_error_ok (&error));
11162                                 }
11163                                 if (pb->cattrs) {
11164                                         if (!method_aux->param_cattr)
11165                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11166                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11167                                 }
11168                         }
11169                 }
11170         }
11171
11172         /* Parameter marshalling */
11173         specs = NULL;
11174         if (rmb->pinfo)         
11175                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11176                         MonoReflectionParamBuilder *pb;
11177                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11178                                 if (pb->marshal_info) {
11179                                         if (specs == NULL)
11180                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11181                                         specs [pb->position] = 
11182                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11183                                 }
11184                         }
11185                 }
11186         if (specs != NULL) {
11187                 if (!method_aux)
11188                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11189                 method_aux->param_marshall = specs;
11190         }
11191
11192         if (image_is_dynamic (klass->image) && method_aux)
11193                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11194
11195         mono_loader_unlock ();
11196
11197         return m;
11198 }       
11199
11200 static MonoMethod*
11201 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11202 {
11203         MonoError error;
11204         ReflectionMethodBuilder rmb;
11205         MonoMethodSignature *sig;
11206
11207         mono_loader_lock ();
11208         sig = ctor_builder_to_signature (klass->image, mb);
11209         mono_loader_unlock ();
11210
11211         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, &error))
11212                 mono_error_raise_exception (&error); /* FIXME don't raise here*/
11213
11214         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11215         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11216
11217         /* If we are in a generic class, we might be called multiple times from inflate_method */
11218         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11219                 /* ilgen is no longer needed */
11220                 mb->ilgen = NULL;
11221         }
11222
11223         return mb->mhandle;
11224 }
11225
11226 static MonoMethod*
11227 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11228 {
11229         MonoError error;
11230         ReflectionMethodBuilder rmb;
11231         MonoMethodSignature *sig;
11232
11233         mono_loader_lock ();
11234         sig = method_builder_to_signature (klass->image, mb);
11235         mono_loader_unlock ();
11236
11237         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, &error))
11238                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11239
11240         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11241         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11242
11243         /* If we are in a generic class, we might be called multiple times from inflate_method */
11244         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11245                 /* ilgen is no longer needed */
11246                 mb->ilgen = NULL;
11247         }
11248         return mb->mhandle;
11249 }
11250
11251 static MonoClassField*
11252 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11253 {
11254         MonoClassField *field;
11255         MonoType *custom;
11256         MonoError error;
11257
11258         field = g_new0 (MonoClassField, 1);
11259
11260         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11261         g_assert (mono_error_ok (&error));
11262         if (fb->attrs || fb->modreq || fb->modopt) {
11263                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11264                 field->type->attrs = fb->attrs;
11265
11266                 g_assert (image_is_dynamic (klass->image));
11267                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11268                 g_free (field->type);
11269                 field->type = mono_metadata_type_dup (klass->image, custom);
11270                 g_free (custom);
11271         } else {
11272                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11273         }
11274         if (fb->offset != -1)
11275                 field->offset = fb->offset;
11276         field->parent = klass;
11277         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11278
11279         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11280
11281         return field;
11282 }
11283 #endif
11284
11285 MonoType*
11286 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11287 {
11288         MonoClass *klass;
11289         MonoReflectionTypeBuilder *tb = NULL;
11290         gboolean is_dynamic = FALSE;
11291         MonoClass *geninst;
11292
11293         mono_loader_lock ();
11294
11295         if (is_sre_type_builder (mono_object_class (type))) {
11296                 tb = (MonoReflectionTypeBuilder *) type;
11297
11298                 is_dynamic = TRUE;
11299         } else if (is_sre_generic_instance (mono_object_class (type))) {
11300                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11301                 MonoReflectionType *gtd = rgi->generic_type;
11302
11303                 if (is_sre_type_builder (mono_object_class (gtd))) {
11304                         tb = (MonoReflectionTypeBuilder *)gtd;
11305                         is_dynamic = TRUE;
11306                 }
11307         }
11308
11309         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11310         if (tb && tb->generic_container)
11311                 mono_reflection_create_generic_class (tb);
11312
11313         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11314         if (!klass->generic_container) {
11315                 mono_loader_unlock ();
11316                 return NULL;
11317         }
11318
11319         if (klass->wastypebuilder) {
11320                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11321
11322                 is_dynamic = TRUE;
11323         }
11324
11325         mono_loader_unlock ();
11326
11327         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11328
11329         return &geninst->byval_arg;
11330 }
11331
11332 MonoClass*
11333 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11334 {
11335         MonoGenericClass *gclass;
11336         MonoGenericInst *inst;
11337
11338         g_assert (klass->generic_container);
11339
11340         inst = mono_metadata_get_generic_inst (type_argc, types);
11341         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11342
11343         return mono_generic_class_get_class (gclass);
11344 }
11345
11346 MonoReflectionMethod*
11347 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11348 {
11349         MonoError error;
11350         MonoClass *klass;
11351         MonoMethod *method, *inflated;
11352         MonoMethodInflated *imethod;
11353         MonoGenericContext tmp_context;
11354         MonoGenericInst *ginst;
11355         MonoType **type_argv;
11356         int count, i;
11357
11358         /*FIXME but this no longer should happen*/
11359         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11360 #ifndef DISABLE_REFLECTION_EMIT
11361                 MonoReflectionMethodBuilder *mb = NULL;
11362                 MonoReflectionTypeBuilder *tb;
11363                 MonoClass *klass;
11364
11365                 mb = (MonoReflectionMethodBuilder *) rmethod;
11366                 tb = (MonoReflectionTypeBuilder *) mb->type;
11367                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11368
11369                 method = methodbuilder_to_mono_method (klass, mb);
11370 #else
11371                 g_assert_not_reached ();
11372                 method = NULL;
11373 #endif
11374         } else {
11375                 method = rmethod->method;
11376         }
11377
11378         klass = method->klass;
11379
11380         if (method->is_inflated)
11381                 method = ((MonoMethodInflated *) method)->declaring;
11382
11383         count = mono_method_signature (method)->generic_param_count;
11384         if (count != mono_array_length (types))
11385                 return NULL;
11386
11387         type_argv = g_new0 (MonoType *, count);
11388         for (i = 0; i < count; i++) {
11389                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11390                 type_argv [i] = mono_reflection_type_get_handle (garg);
11391         }
11392         ginst = mono_metadata_get_generic_inst (count, type_argv);
11393         g_free (type_argv);
11394
11395         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11396         tmp_context.method_inst = ginst;
11397
11398         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11399         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11400         imethod = (MonoMethodInflated *) inflated;
11401
11402         /*FIXME but I think this is no longer necessary*/
11403         if (image_is_dynamic (method->klass->image)) {
11404                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11405                 /*
11406                  * This table maps metadata structures representing inflated methods/fields
11407                  * to the reflection objects representing their generic definitions.
11408                  */
11409                 mono_image_lock ((MonoImage*)image);
11410                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11411                 mono_image_unlock ((MonoImage*)image);
11412         }
11413
11414         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11415                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11416         
11417         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11418         mono_error_raise_exception (&error); /* FIXME don't raise here */
11419         return ret;
11420 }
11421
11422 #ifndef DISABLE_REFLECTION_EMIT
11423
11424 static MonoMethod *
11425 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11426 {
11427         MonoMethodInflated *imethod;
11428         MonoGenericContext *context;
11429         int i;
11430
11431         /*
11432          * With generic code sharing the klass might not be inflated.
11433          * This can happen because classes inflated with their own
11434          * type arguments are "normalized" to the uninflated class.
11435          */
11436         if (!klass->generic_class)
11437                 return method;
11438
11439         context = mono_class_get_context (klass);
11440
11441         if (klass->method.count && klass->methods) {
11442                 /* Find the already created inflated method */
11443                 for (i = 0; i < klass->method.count; ++i) {
11444                         g_assert (klass->methods [i]->is_inflated);
11445                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11446                                 break;
11447                 }
11448                 g_assert (i < klass->method.count);
11449                 imethod = (MonoMethodInflated*)klass->methods [i];
11450         } else {
11451                 MonoError error;
11452                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11453                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11454         }
11455
11456         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11457                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11458
11459                 mono_image_lock ((MonoImage*)image);
11460                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11461                 mono_image_unlock ((MonoImage*)image);
11462         }
11463         return (MonoMethod *) imethod;
11464 }
11465
11466 static MonoMethod *
11467 inflate_method (MonoReflectionType *type, MonoObject *obj)
11468 {
11469         MonoMethod *method;
11470         MonoClass *gklass;
11471
11472         MonoClass *type_class = mono_object_class (type);
11473
11474         if (is_sre_generic_instance (type_class)) {
11475                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11476                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11477         } else if (is_sre_type_builder (type_class)) {
11478                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11479         } else if (type->type) {
11480                 gklass = mono_class_from_mono_type (type->type);
11481                 gklass = mono_class_get_generic_type_definition (gklass);
11482         } else {
11483                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11484         }
11485
11486         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11487                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11488                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11489                 else
11490                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11491         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11492                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11493         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11494                 method = ((MonoReflectionMethod *) obj)->method;
11495         else {
11496                 method = NULL; /* prevent compiler warning */
11497                 g_error ("can't handle type %s", obj->vtable->klass->name);
11498         }
11499
11500         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11501 }
11502
11503 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11504 void
11505 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11506 {
11507         MonoGenericClass *gclass;
11508         MonoDynamicGenericClass *dgclass;
11509         MonoClass *klass, *gklass;
11510         MonoType *gtype;
11511         int i;
11512
11513         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11514         klass = mono_class_from_mono_type (gtype);
11515         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11516         gclass = gtype->data.generic_class;
11517
11518         if (!gclass->is_dynamic)
11519                 return;
11520
11521         dgclass = (MonoDynamicGenericClass *) gclass;
11522
11523         if (dgclass->initialized)
11524                 return;
11525
11526         gklass = gclass->container_class;
11527         mono_class_init (gklass);
11528
11529         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11530
11531         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11532         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11533         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11534
11535         for (i = 0; i < dgclass->count_fields; i++) {
11536                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11537                 MonoClassField *field, *inflated_field = NULL;
11538
11539                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11540                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11541                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11542                         field = ((MonoReflectionField *) obj)->field;
11543                 else {
11544                         field = NULL; /* prevent compiler warning */
11545                         g_assert_not_reached ();
11546                 }
11547
11548                 dgclass->fields [i] = *field;
11549                 dgclass->fields [i].parent = klass;
11550                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11551                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11552                 dgclass->field_generic_types [i] = field->type;
11553                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11554                 dgclass->field_objects [i] = obj;
11555
11556                 if (inflated_field) {
11557                         g_free (inflated_field);
11558                 } else {
11559                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11560                 }
11561         }
11562
11563         dgclass->initialized = TRUE;
11564 }
11565
11566 void
11567 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11568 {
11569         MonoDynamicGenericClass *dgclass;
11570         int i;
11571
11572         g_assert (gclass->is_dynamic);
11573
11574         dgclass = (MonoDynamicGenericClass *)gclass;
11575
11576         for (i = 0; i < dgclass->count_fields; ++i) {
11577                 MonoClassField *field = dgclass->fields + i;
11578                 mono_metadata_free_type (field->type);
11579                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11580         }
11581 }
11582
11583 static void
11584 fix_partial_generic_class (MonoClass *klass)
11585 {
11586         MonoClass *gklass = klass->generic_class->container_class;
11587         MonoDynamicGenericClass *dgclass;
11588         int i;
11589
11590         if (klass->wastypebuilder)
11591                 return;
11592
11593         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11594         if (klass->parent != gklass->parent) {
11595                 MonoError error;
11596                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11597                 if (mono_error_ok (&error)) {
11598                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11599                         mono_metadata_free_type (parent_type);
11600                         if (parent != klass->parent) {
11601                                 /*fool mono_class_setup_parent*/
11602                                 klass->supertypes = NULL;
11603                                 mono_class_setup_parent (klass, parent);
11604                         }
11605                 } else {
11606                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11607                         mono_error_cleanup (&error);
11608                         if (gklass->wastypebuilder)
11609                                 klass->wastypebuilder = TRUE;
11610                         return;
11611                 }
11612         }
11613
11614         if (!dgclass->initialized)
11615                 return;
11616
11617         if (klass->method.count != gklass->method.count) {
11618                 klass->method.count = gklass->method.count;
11619                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11620
11621                 for (i = 0; i < klass->method.count; i++) {
11622                         MonoError error;
11623                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11624                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11625                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11626                 }
11627         }
11628
11629         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11630                 klass->interface_count = gklass->interface_count;
11631                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11632                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11633
11634                 for (i = 0; i < gklass->interface_count; ++i) {
11635                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11636                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11637                         mono_metadata_free_type (iface_type);
11638
11639                         ensure_runtime_vtable (klass->interfaces [i]);
11640                 }
11641                 klass->interfaces_inited = 1;
11642         }
11643
11644         if (klass->field.count != gklass->field.count) {
11645                 klass->field.count = gklass->field.count;
11646                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11647
11648                 for (i = 0; i < klass->field.count; i++) {
11649                         klass->fields [i] = gklass->fields [i];
11650                         klass->fields [i].parent = klass;
11651                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11652                 }
11653         }
11654
11655         /*We can only finish with this klass once it's parent has as well*/
11656         if (gklass->wastypebuilder)
11657                 klass->wastypebuilder = TRUE;
11658         return;
11659 }
11660
11661 static void
11662 ensure_generic_class_runtime_vtable (MonoClass *klass)
11663 {
11664         MonoClass *gklass = klass->generic_class->container_class;
11665
11666         ensure_runtime_vtable (gklass); 
11667
11668         fix_partial_generic_class (klass);
11669 }
11670
11671 static void
11672 ensure_runtime_vtable (MonoClass *klass)
11673 {
11674         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11675         int i, num, j;
11676
11677         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11678                 return;
11679         if (klass->parent)
11680                 ensure_runtime_vtable (klass->parent);
11681
11682         if (tb) {
11683                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11684                 num += tb->num_methods;
11685                 klass->method.count = num;
11686                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11687                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11688                 for (i = 0; i < num; ++i)
11689                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11690                 num = tb->num_methods;
11691                 j = i;
11692                 for (i = 0; i < num; ++i)
11693                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11694         
11695                 if (tb->interfaces) {
11696                         klass->interface_count = mono_array_length (tb->interfaces);
11697                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11698                         for (i = 0; i < klass->interface_count; ++i) {
11699                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11700                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11701                                 ensure_runtime_vtable (klass->interfaces [i]);
11702                         }
11703                         klass->interfaces_inited = 1;
11704                 }
11705         } else if (klass->generic_class){
11706                 ensure_generic_class_runtime_vtable (klass);
11707         }
11708
11709         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11710                 int slot_num = 0;
11711                 for (i = 0; i < klass->method.count; ++i) {
11712                         MonoMethod *im = klass->methods [i];
11713                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11714                                 im->slot = slot_num++;
11715                 }
11716                 
11717                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11718                 mono_class_setup_interface_offsets (klass);
11719                 mono_class_setup_interface_id (klass);
11720         }
11721
11722         /*
11723          * The generic vtable is needed even if image->run is not set since some
11724          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11725          * method->slot being defined.
11726          */
11727
11728         /* 
11729          * tb->methods could not be freed since it is used for determining 
11730          * overrides during dynamic vtable construction.
11731          */
11732 }
11733
11734 static MonoMethod*
11735 mono_reflection_method_get_handle (MonoObject *method)
11736 {
11737         MonoClass *klass = mono_object_class (method);
11738         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11739                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11740                 return sr_method->method;
11741         }
11742         if (is_sre_method_builder (klass)) {
11743                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11744                 return mb->mhandle;
11745         }
11746         if (is_sre_method_on_tb_inst (klass)) {
11747                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11748                 MonoMethod *result;
11749                 /*FIXME move this to a proper method and unify with resolve_object*/
11750                 if (m->method_args) {
11751                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11752                 } else {
11753                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11754                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11755                         MonoMethod *mono_method;
11756
11757                         if (is_sre_method_builder (mono_object_class (m->mb)))
11758                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11759                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11760                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11761                         else
11762                                 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)));
11763
11764                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11765                 }
11766                 return result;
11767         }
11768
11769         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11770         return NULL;
11771 }
11772
11773 void
11774 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11775 {
11776         MonoReflectionTypeBuilder *tb;
11777         int i, j, onum;
11778         MonoReflectionMethod *m;
11779
11780         *overrides = NULL;
11781         *num_overrides = 0;
11782
11783         g_assert (image_is_dynamic (klass->image));
11784
11785         if (!mono_class_get_ref_info (klass))
11786                 return;
11787
11788         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11789
11790         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11791
11792         onum = 0;
11793         if (tb->methods) {
11794                 for (i = 0; i < tb->num_methods; ++i) {
11795                         MonoReflectionMethodBuilder *mb = 
11796                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11797                         if (mb->override_methods)
11798                                 onum += mono_array_length (mb->override_methods);
11799                 }
11800         }
11801
11802         if (onum) {
11803                 *overrides = g_new0 (MonoMethod*, onum * 2);
11804
11805                 onum = 0;
11806                 for (i = 0; i < tb->num_methods; ++i) {
11807                         MonoReflectionMethodBuilder *mb = 
11808                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11809                         if (mb->override_methods) {
11810                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11811                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11812
11813                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11814                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11815
11816                                         g_assert (mb->mhandle);
11817
11818                                         onum ++;
11819                                 }
11820                         }
11821                 }
11822         }
11823
11824         *num_overrides = onum;
11825 }
11826
11827 static void
11828 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11829 {
11830         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11831         MonoReflectionFieldBuilder *fb;
11832         MonoClassField *field;
11833         MonoImage *image = klass->image;
11834         const char *p, *p2;
11835         int i;
11836         guint32 len, idx, real_size = 0;
11837
11838         klass->field.count = tb->num_fields;
11839         klass->field.first = 0;
11840
11841         mono_error_init (error);
11842
11843         if (tb->class_size) {
11844                 if ((tb->packing_size & 0xffffff00) != 0) {
11845                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11846                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11847                         return;
11848                 }
11849                 klass->packing_size = tb->packing_size;
11850                 real_size = klass->instance_size + tb->class_size;
11851         }
11852
11853         if (!klass->field.count) {
11854                 klass->instance_size = MAX (klass->instance_size, real_size);
11855                 return;
11856         }
11857         
11858         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11859         mono_class_alloc_ext (klass);
11860         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11861         /*
11862         This is, guess what, a hack.
11863         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11864         On the static path no field class is resolved, only types are built. This is the right thing to do
11865         but we suck.
11866         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11867         */
11868         klass->size_inited = 1;
11869
11870         for (i = 0; i < klass->field.count; ++i) {
11871                 MonoArray *rva_data;
11872                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11873                 field = &klass->fields [i];
11874                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11875                 if (!mono_error_ok (error))
11876                         return;
11877                 if (fb->attrs) {
11878                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11879                         field->type->attrs = fb->attrs;
11880                 } else {
11881                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11882                 }
11883
11884                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11885                         char *base = mono_array_addr (rva_data, char, 0);
11886                         size_t size = mono_array_length (rva_data);
11887                         char *data = (char *)mono_image_alloc (klass->image, size);
11888                         memcpy (data, base, size);
11889                         klass->ext->field_def_values [i].data = data;
11890                 }
11891                 if (fb->offset != -1)
11892                         field->offset = fb->offset;
11893                 field->parent = klass;
11894                 fb->handle = field;
11895                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11896
11897                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11898                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11899                 }
11900                 if (fb->def_value) {
11901                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11902                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11903                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11904                         /* Copy the data from the blob since it might get realloc-ed */
11905                         p = assembly->blob.data + idx;
11906                         len = mono_metadata_decode_blob_size (p, &p2);
11907                         len += p2 - p;
11908                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11909                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11910                 }
11911         }
11912
11913         klass->instance_size = MAX (klass->instance_size, real_size);
11914         mono_class_layout_fields (klass);
11915 }
11916
11917 static void
11918 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11919 {
11920         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11921         MonoReflectionPropertyBuilder *pb;
11922         MonoImage *image = klass->image;
11923         MonoProperty *properties;
11924         int i;
11925
11926         mono_error_init (error);
11927
11928         if (!klass->ext)
11929                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11930
11931         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11932         klass->ext->property.first = 0;
11933
11934         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11935         klass->ext->properties = properties;
11936         for (i = 0; i < klass->ext->property.count; ++i) {
11937                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11938                 properties [i].parent = klass;
11939                 properties [i].attrs = pb->attrs;
11940                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11941                 if (!mono_error_ok (error))
11942                         return;
11943                 if (pb->get_method)
11944                         properties [i].get = pb->get_method->mhandle;
11945                 if (pb->set_method)
11946                         properties [i].set = pb->set_method->mhandle;
11947
11948                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11949                 if (pb->def_value) {
11950                         guint32 len, idx;
11951                         const char *p, *p2;
11952                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11953                         if (!klass->ext->prop_def_values)
11954                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11955                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11956                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11957                         /* Copy the data from the blob since it might get realloc-ed */
11958                         p = assembly->blob.data + idx;
11959                         len = mono_metadata_decode_blob_size (p, &p2);
11960                         len += p2 - p;
11961                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11962                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11963                 }
11964         }
11965 }
11966
11967 MonoReflectionEvent *
11968 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11969 {
11970         MonoEvent *event = g_new0 (MonoEvent, 1);
11971         MonoClass *klass;
11972
11973         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11974
11975         event->parent = klass;
11976         event->attrs = eb->attrs;
11977         event->name = mono_string_to_utf8 (eb->name);
11978         if (eb->add_method)
11979                 event->add = eb->add_method->mhandle;
11980         if (eb->remove_method)
11981                 event->remove = eb->remove_method->mhandle;
11982         if (eb->raise_method)
11983                 event->raise = eb->raise_method->mhandle;
11984
11985 #ifndef MONO_SMALL_CONFIG
11986         if (eb->other_methods) {
11987                 int j;
11988                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11989                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11990                         MonoReflectionMethodBuilder *mb = 
11991                                 mono_array_get (eb->other_methods,
11992                                                 MonoReflectionMethodBuilder*, j);
11993                         event->other [j] = mb->mhandle;
11994                 }
11995         }
11996 #endif
11997
11998         return mono_event_get_object (mono_object_domain (tb), klass, event);
11999 }
12000
12001 static void
12002 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12003 {
12004         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12005         MonoReflectionEventBuilder *eb;
12006         MonoImage *image = klass->image;
12007         MonoEvent *events;
12008         int i;
12009
12010         mono_error_init (error);
12011
12012         if (!klass->ext)
12013                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12014
12015         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12016         klass->ext->event.first = 0;
12017
12018         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12019         klass->ext->events = events;
12020         for (i = 0; i < klass->ext->event.count; ++i) {
12021                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12022                 events [i].parent = klass;
12023                 events [i].attrs = eb->attrs;
12024                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12025                 if (!mono_error_ok (error))
12026                         return;
12027                 if (eb->add_method)
12028                         events [i].add = eb->add_method->mhandle;
12029                 if (eb->remove_method)
12030                         events [i].remove = eb->remove_method->mhandle;
12031                 if (eb->raise_method)
12032                         events [i].raise = eb->raise_method->mhandle;
12033
12034 #ifndef MONO_SMALL_CONFIG
12035                 if (eb->other_methods) {
12036                         int j;
12037                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12038                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12039                                 MonoReflectionMethodBuilder *mb = 
12040                                         mono_array_get (eb->other_methods,
12041                                                                         MonoReflectionMethodBuilder*, j);
12042                                 events [i].other [j] = mb->mhandle;
12043                         }
12044                 }
12045 #endif
12046                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12047         }
12048 }
12049
12050 static gboolean
12051 remove_instantiations_of_and_ensure_contents (gpointer key,
12052                                                   gpointer value,
12053                                                   gpointer user_data)
12054 {
12055         MonoType *type = (MonoType*)key;
12056         MonoClass *klass = (MonoClass*)user_data;
12057
12058         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12059                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12060                 return TRUE;
12061         } else
12062                 return FALSE;
12063 }
12064
12065 static void
12066 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12067 {
12068         mono_error_init (error);
12069         int i;
12070
12071         if (!arr)
12072                 return;
12073
12074         for (i = 0; i < mono_array_length (arr); ++i) {
12075                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12076                 if (!mono_error_ok (error))
12077                         break;
12078         }
12079 }
12080
12081 MonoReflectionType*
12082 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12083 {
12084         MonoError error;
12085         MonoClass *klass;
12086         MonoDomain* domain;
12087         MonoReflectionType* res;
12088         int i, j;
12089
12090         domain = mono_object_domain (tb);
12091         klass = mono_class_from_mono_type (tb->type.type);
12092
12093         /*
12094          * Check for user defined Type subclasses.
12095          */
12096         RESOLVE_TYPE (tb->parent, &error);
12097         mono_error_raise_exception (&error); /* FIXME don't raise here */
12098         check_array_for_usertypes (tb->interfaces, &error);
12099         mono_error_raise_exception (&error); /*FIXME don't raise here */
12100         if (tb->fields) {
12101                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12102                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12103                         if (fb) {
12104                                 RESOLVE_TYPE (fb->type, &error);
12105                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12106                                 check_array_for_usertypes (fb->modreq, &error);
12107                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12108                                 check_array_for_usertypes (fb->modopt, &error);
12109                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12110                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12111                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12112                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12113                                 }
12114                         }
12115                 }
12116         }
12117         if (tb->methods) {
12118                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12119                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12120                         if (mb) {
12121                                 RESOLVE_TYPE (mb->rtype, &error);
12122                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12123                                 check_array_for_usertypes (mb->return_modreq, &error);
12124                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12125                                 check_array_for_usertypes (mb->return_modopt, &error);
12126                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12127                                 check_array_for_usertypes (mb->parameters, &error);
12128                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12129                                 if (mb->param_modreq)
12130                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12131                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12132                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12133                                         }
12134                                 if (mb->param_modopt)
12135                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12136                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12137                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12138                                         }
12139                         }
12140                 }
12141         }
12142         if (tb->ctors) {
12143                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12144                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12145                         if (mb) {
12146                                 check_array_for_usertypes (mb->parameters, &error);
12147                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12148                                 if (mb->param_modreq)
12149                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12150                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12151                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12152                                         }
12153                                 if (mb->param_modopt)
12154                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12155                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12156                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12157                                         }
12158                         }
12159                 }
12160         }
12161
12162         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12163
12164         /* 
12165          * we need to lock the domain because the lock will be taken inside
12166          * So, we need to keep the locking order correct.
12167          */
12168         mono_loader_lock ();
12169         mono_domain_lock (domain);
12170         if (klass->wastypebuilder) {
12171                 mono_domain_unlock (domain);
12172                 mono_loader_unlock ();
12173
12174                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12175                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12176
12177                 return res;
12178         }
12179         /*
12180          * Fields to set in klass:
12181          * the various flags: delegate/unicode/contextbound etc.
12182          */
12183         klass->flags = tb->attrs;
12184         klass->has_cctor = 1;
12185         klass->has_finalize = 1;
12186         klass->has_finalize_inited = 1;
12187
12188         mono_class_setup_parent (klass, klass->parent);
12189         /* fool mono_class_setup_supertypes */
12190         klass->supertypes = NULL;
12191         mono_class_setup_supertypes (klass);
12192         mono_class_setup_mono_type (klass);
12193
12194 #if 0
12195         if (!((MonoDynamicImage*)klass->image)->run) {
12196                 if (klass->generic_container) {
12197                         /* FIXME: The code below can't handle generic classes */
12198                         klass->wastypebuilder = TRUE;
12199                         mono_loader_unlock ();
12200                         mono_domain_unlock (domain);
12201
12202                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12203                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12204
12205                         return res;
12206                 }
12207         }
12208 #endif
12209
12210         /* enums are done right away */
12211         if (!klass->enumtype)
12212                 ensure_runtime_vtable (klass);
12213
12214         if (tb->subtypes) {
12215                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12216                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12217                         mono_class_alloc_ext (klass);
12218                         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)));
12219                 }
12220         }
12221
12222         klass->nested_classes_inited = TRUE;
12223
12224         /* fields and object layout */
12225         if (klass->parent) {
12226                 if (!klass->parent->size_inited)
12227                         mono_class_init (klass->parent);
12228                 klass->instance_size = klass->parent->instance_size;
12229                 klass->sizes.class_size = 0;
12230                 klass->min_align = klass->parent->min_align;
12231                 /* if the type has no fields we won't call the field_setup
12232                  * routine which sets up klass->has_references.
12233                  */
12234                 klass->has_references |= klass->parent->has_references;
12235         } else {
12236                 klass->instance_size = sizeof (MonoObject);
12237                 klass->min_align = 1;
12238         }
12239
12240         /* FIXME: handle packing_size and instance_size */
12241         typebuilder_setup_fields (klass, &error);
12242         if (!mono_error_ok (&error))
12243                 goto failure;
12244         typebuilder_setup_properties (klass, &error);
12245         if (!mono_error_ok (&error))
12246                 goto failure;
12247
12248         typebuilder_setup_events (klass, &error);
12249         if (!mono_error_ok (&error))
12250                 goto failure;
12251
12252         klass->wastypebuilder = TRUE;
12253
12254         /* 
12255          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12256          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12257          * we want to return normal System.MonoType objects, so clear these out from the cache.
12258          *
12259          * Together with this we must ensure the contents of all instances to match the created type.
12260          */
12261         if (domain->type_hash && klass->generic_container)
12262                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12263
12264         mono_domain_unlock (domain);
12265         mono_loader_unlock ();
12266
12267         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12268                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12269                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12270         }
12271
12272         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12273         mono_error_raise_exception (&error); /* FIXME don't raise here */
12274
12275         g_assert (res != (MonoReflectionType*)tb);
12276
12277         return res;
12278
12279 failure:
12280         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12281         klass->wastypebuilder = TRUE;
12282         mono_domain_unlock (domain);
12283         mono_loader_unlock ();
12284         mono_error_raise_exception (&error);
12285         return NULL;
12286 }
12287
12288 void
12289 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12290 {
12291         MonoGenericParamFull *param;
12292         MonoImage *image;
12293         MonoClass *pklass;
12294         MonoError error;
12295
12296         image = &gparam->tbuilder->module->dynamic_image->image;
12297
12298         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12299
12300         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12301         g_assert (mono_error_ok (&error));
12302         param->param.num = gparam->index;
12303
12304         if (gparam->mbuilder) {
12305                 if (!gparam->mbuilder->generic_container) {
12306                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12307                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12308                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12309                         gparam->mbuilder->generic_container->is_method = TRUE;
12310                         /* 
12311                          * Cannot set owner.method, since the MonoMethod is not created yet.
12312                          * Set the image field instead, so type_in_image () works.
12313                          */
12314                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12315                         gparam->mbuilder->generic_container->owner.image = klass->image;
12316                 }
12317                 param->param.owner = gparam->mbuilder->generic_container;
12318         } else if (gparam->tbuilder) {
12319                 if (!gparam->tbuilder->generic_container) {
12320                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12321                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12322                         gparam->tbuilder->generic_container->owner.klass = klass;
12323                 }
12324                 param->param.owner = gparam->tbuilder->generic_container;
12325         }
12326
12327         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12328
12329         gparam->type.type = &pklass->byval_arg;
12330
12331         mono_class_set_ref_info (pklass, gparam);
12332         mono_image_append_class_to_reflection_info_set (pklass);
12333 }
12334
12335 MonoArray *
12336 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12337 {
12338         MonoError error;
12339         MonoReflectionModuleBuilder *module = sig->module;
12340         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12341         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12342         guint32 buflen, i;
12343         MonoArray *result;
12344         SigBuffer buf;
12345
12346         check_array_for_usertypes (sig->arguments, &error);
12347         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12348
12349         sigbuffer_init (&buf, 32);
12350
12351         sigbuffer_add_value (&buf, 0x07);
12352         sigbuffer_add_value (&buf, na);
12353         if (assembly != NULL){
12354                 for (i = 0; i < na; ++i) {
12355                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12356                         encode_reflection_type (assembly, type, &buf);
12357                 }
12358         }
12359
12360         buflen = buf.p - buf.buf;
12361         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12362         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12363         sigbuffer_free (&buf);
12364
12365         return result;
12366 }
12367
12368 MonoArray *
12369 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12370 {
12371         MonoError error;
12372         MonoDynamicImage *assembly = sig->module->dynamic_image;
12373         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12374         guint32 buflen, i;
12375         MonoArray *result;
12376         SigBuffer buf;
12377
12378         check_array_for_usertypes (sig->arguments, &error);
12379         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12380
12381         sigbuffer_init (&buf, 32);
12382
12383         sigbuffer_add_value (&buf, 0x06);
12384         for (i = 0; i < na; ++i) {
12385                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12386                 encode_reflection_type (assembly, type, &buf);
12387         }
12388
12389         buflen = buf.p - buf.buf;
12390         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12391         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12392         sigbuffer_free (&buf);
12393
12394         return result;
12395 }
12396
12397 typedef struct {
12398         MonoMethod *handle;
12399         MonoDomain *domain;
12400 } DynamicMethodReleaseData;
12401
12402 /*
12403  * The runtime automatically clean up those after finalization.
12404 */      
12405 static MonoReferenceQueue *dynamic_method_queue;
12406
12407 static void
12408 free_dynamic_method (void *dynamic_method)
12409 {
12410         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12411         MonoDomain *domain = data->domain;
12412         MonoMethod *method = data->handle;
12413         guint32 dis_link;
12414
12415         mono_domain_lock (domain);
12416         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12417         g_hash_table_remove (domain->method_to_dyn_method, method);
12418         mono_domain_unlock (domain);
12419         g_assert (dis_link);
12420         mono_gchandle_free (dis_link);
12421
12422         mono_runtime_free_method (domain, method);
12423         g_free (data);
12424 }
12425
12426 void 
12427 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12428 {
12429         MonoReferenceQueue *queue;
12430         MonoMethod *handle;
12431         DynamicMethodReleaseData *release_data;
12432         ReflectionMethodBuilder rmb;
12433         MonoMethodSignature *sig;
12434         MonoClass *klass;
12435         MonoDomain *domain;
12436         GSList *l;
12437         int i;
12438
12439         if (mono_runtime_is_shutting_down ())
12440                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12441
12442         if (!(queue = dynamic_method_queue)) {
12443                 mono_loader_lock ();
12444                 if (!(queue = dynamic_method_queue))
12445                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12446                 mono_loader_unlock ();
12447         }
12448
12449         sig = dynamic_method_to_signature (mb);
12450
12451         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12452
12453         /*
12454          * Resolve references.
12455          */
12456         /* 
12457          * Every second entry in the refs array is reserved for storing handle_class,
12458          * which is needed by the ldtoken implementation in the JIT.
12459          */
12460         rmb.nrefs = mb->nrefs;
12461         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12462         for (i = 0; i < mb->nrefs; i += 2) {
12463                 MonoClass *handle_class;
12464                 gpointer ref;
12465                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12466
12467                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12468                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12469                         /*
12470                          * The referenced DynamicMethod should already be created by the managed
12471                          * code, except in the case of circular references. In that case, we store
12472                          * method in the refs array, and fix it up later when the referenced 
12473                          * DynamicMethod is created.
12474                          */
12475                         if (method->mhandle) {
12476                                 ref = method->mhandle;
12477                         } else {
12478                                 /* FIXME: GC object stored in unmanaged memory */
12479                                 ref = method;
12480
12481                                 /* FIXME: GC object stored in unmanaged memory */
12482                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12483                         }
12484                         handle_class = mono_defaults.methodhandle_class;
12485                 } else {
12486                         MonoException *ex = NULL;
12487                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12488                         if (!ref)
12489                                 ex = mono_get_exception_type_load (NULL, NULL);
12490                         else if (mono_security_core_clr_enabled ())
12491                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12492
12493                         if (ex) {
12494                                 g_free (rmb.refs);
12495                                 mono_raise_exception (ex);
12496                                 return;
12497                         }
12498                 }
12499
12500                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12501                 rmb.refs [i + 1] = handle_class;
12502         }               
12503
12504         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12505
12506         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12507         release_data = g_new (DynamicMethodReleaseData, 1);
12508         release_data->handle = handle;
12509         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12510         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12511                 g_free (release_data);
12512
12513         /* Fix up refs entries pointing at us */
12514         for (l = mb->referenced_by; l; l = l->next) {
12515                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12516                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12517                 gpointer *data;
12518                 
12519                 g_assert (method->mhandle);
12520
12521                 data = (gpointer*)wrapper->method_data;
12522                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12523                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12524                                 data [i + 1] = mb->mhandle;
12525                 }
12526         }
12527         g_slist_free (mb->referenced_by);
12528
12529         g_free (rmb.refs);
12530
12531         /* ilgen is no longer needed */
12532         mb->ilgen = NULL;
12533
12534         domain = mono_domain_get ();
12535         mono_domain_lock (domain);
12536         if (!domain->method_to_dyn_method)
12537                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12538         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12539         mono_domain_unlock (domain);
12540 }
12541
12542 #endif /* DISABLE_REFLECTION_EMIT */
12543
12544 /**
12545  * 
12546  * mono_reflection_is_valid_dynamic_token:
12547  * 
12548  * Returns TRUE if token is valid.
12549  * 
12550  */
12551 gboolean
12552 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12553 {
12554         return lookup_dyn_token (image, token) != NULL;
12555 }
12556
12557 MonoMethodSignature *
12558 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12559 {
12560         MonoMethodSignature *sig;
12561         g_assert (image_is_dynamic (image));
12562
12563         mono_error_init (error);
12564
12565         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12566         if (sig)
12567                 return sig;
12568
12569         return mono_method_signature_checked (method, error);
12570 }
12571
12572 #ifndef DISABLE_REFLECTION_EMIT
12573
12574 /**
12575  * mono_reflection_lookup_dynamic_token:
12576  *
12577  * Finish the Builder object pointed to by TOKEN and return the corresponding
12578  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12579  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12580  * mapping table.
12581  *
12582  * LOCKING: Take the loader lock
12583  */
12584 gpointer
12585 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12586 {
12587         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12588         MonoObject *obj;
12589         MonoClass *klass;
12590
12591         obj = lookup_dyn_token (assembly, token);
12592         if (!obj) {
12593                 if (valid_token)
12594                         g_error ("Could not find required dynamic token 0x%08x", token);
12595                 else
12596                         return NULL;
12597         }
12598
12599         if (!handle_class)
12600                 handle_class = &klass;
12601         return resolve_object (image, obj, handle_class, context);
12602 }
12603
12604 /*
12605  * ensure_complete_type:
12606  *
12607  *   Ensure that KLASS is completed if it is a dynamic type, or references
12608  * dynamic types.
12609  */
12610 static void
12611 ensure_complete_type (MonoClass *klass)
12612 {
12613         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12614                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12615
12616                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12617
12618                 // Asserting here could break a lot of code
12619                 //g_assert (klass->wastypebuilder);
12620         }
12621
12622         if (klass->generic_class) {
12623                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12624                 int i;
12625
12626                 for (i = 0; i < inst->type_argc; ++i) {
12627                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12628                 }
12629         }
12630 }
12631
12632 static gpointer
12633 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12634 {
12635         gpointer result = NULL;
12636
12637         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12638                 result = mono_string_intern ((MonoString*)obj);
12639                 *handle_class = mono_defaults.string_class;
12640                 g_assert (result);
12641         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12642                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12643                 MonoClass *mc = mono_class_from_mono_type (type);
12644                 if (!mono_class_init (mc))
12645                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12646
12647                 if (context) {
12648                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12649                         result = mono_class_from_mono_type (inflated);
12650                         mono_metadata_free_type (inflated);
12651                 } else {
12652                         result = mono_class_from_mono_type (type);
12653                 }
12654                 *handle_class = mono_defaults.typehandle_class;
12655                 g_assert (result);
12656         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12657                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12658                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12659                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12660                 result = ((MonoReflectionMethod*)obj)->method;
12661                 if (context) {
12662                         MonoError error;
12663                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12664                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12665                 }
12666                 *handle_class = mono_defaults.methodhandle_class;
12667                 g_assert (result);
12668         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12669                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12670                 result = mb->mhandle;
12671                 if (!result) {
12672                         /* Type is not yet created */
12673                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12674
12675                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12676
12677                         /*
12678                          * Hopefully this has been filled in by calling CreateType() on the
12679                          * TypeBuilder.
12680                          */
12681                         /*
12682                          * TODO: This won't work if the application finishes another 
12683                          * TypeBuilder instance instead of this one.
12684                          */
12685                         result = mb->mhandle;
12686                 }
12687                 if (context) {
12688                         MonoError error;
12689                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12690                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12691                 }
12692                 *handle_class = mono_defaults.methodhandle_class;
12693         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12694                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12695
12696                 result = cb->mhandle;
12697                 if (!result) {
12698                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12699
12700                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12701                         result = cb->mhandle;
12702                 }
12703                 if (context) {
12704                         MonoError error;
12705                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12706                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12707                 }
12708                 *handle_class = mono_defaults.methodhandle_class;
12709         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12710                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12711
12712                 ensure_complete_type (field->parent);
12713                 if (context) {
12714                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12715                         MonoClass *klass = mono_class_from_mono_type (inflated);
12716                         MonoClassField *inflated_field;
12717                         gpointer iter = NULL;
12718                         mono_metadata_free_type (inflated);
12719                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12720                                 if (!strcmp (field->name, inflated_field->name))
12721                                         break;
12722                         }
12723                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12724                         result = inflated_field;
12725                 } else {
12726                         result = field;
12727                 }
12728                 *handle_class = mono_defaults.fieldhandle_class;
12729                 g_assert (result);
12730         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12731                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12732                 result = fb->handle;
12733
12734                 if (!result) {
12735                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12736
12737                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12738                         result = fb->handle;
12739                 }
12740
12741                 if (fb->handle && fb->handle->parent->generic_container) {
12742                         MonoClass *klass = fb->handle->parent;
12743                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12744                         MonoClass *inflated = mono_class_from_mono_type (type);
12745
12746                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12747                         g_assert (result);
12748                         mono_metadata_free_type (type);
12749                 }
12750                 *handle_class = mono_defaults.fieldhandle_class;
12751         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12752                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12753                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12754                 MonoClass *klass;
12755
12756                 klass = type->data.klass;
12757                 if (klass->wastypebuilder) {
12758                         /* Already created */
12759                         result = klass;
12760                 }
12761                 else {
12762                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12763                         result = type->data.klass;
12764                         g_assert (result);
12765                 }
12766                 *handle_class = mono_defaults.typehandle_class;
12767         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12768                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12769                 MonoMethodSignature *sig;
12770                 int nargs, i;
12771
12772                 if (helper->arguments)
12773                         nargs = mono_array_length (helper->arguments);
12774                 else
12775                         nargs = 0;
12776
12777                 sig = mono_metadata_signature_alloc (image, nargs);
12778                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12779                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12780
12781                 if (helper->unmanaged_call_conv) { /* unmanaged */
12782                         sig->call_convention = helper->unmanaged_call_conv - 1;
12783                         sig->pinvoke = TRUE;
12784                 } else if (helper->call_conv & 0x02) {
12785                         sig->call_convention = MONO_CALL_VARARG;
12786                 } else {
12787                         sig->call_convention = MONO_CALL_DEFAULT;
12788                 }
12789
12790                 sig->param_count = nargs;
12791                 /* TODO: Copy type ? */
12792                 sig->ret = helper->return_type->type;
12793                 for (i = 0; i < nargs; ++i)
12794                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12795
12796                 result = sig;
12797                 *handle_class = NULL;
12798         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12799                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12800                 /* Already created by the managed code */
12801                 g_assert (method->mhandle);
12802                 result = method->mhandle;
12803                 *handle_class = mono_defaults.methodhandle_class;
12804         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12805                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12806                 type = mono_class_inflate_generic_type (type, context);
12807                 result = mono_class_from_mono_type (type);
12808                 *handle_class = mono_defaults.typehandle_class;
12809                 g_assert (result);
12810                 mono_metadata_free_type (type);
12811         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12812                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12813                 type = mono_class_inflate_generic_type (type, context);
12814                 result = mono_class_from_mono_type (type);
12815                 *handle_class = mono_defaults.typehandle_class;
12816                 g_assert (result);
12817                 mono_metadata_free_type (type);
12818         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12819                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12820                 MonoClass *inflated;
12821                 MonoType *type;
12822                 MonoClassField *field;
12823
12824                 if (is_sre_field_builder (mono_object_class (f->fb)))
12825                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12826                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12827                         field = ((MonoReflectionField*)f->fb)->field;
12828                 else
12829                         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)));
12830
12831                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12832                 inflated = mono_class_from_mono_type (type);
12833
12834                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12835                 ensure_complete_type (field->parent);
12836                 g_assert (result);
12837                 mono_metadata_free_type (type);
12838                 *handle_class = mono_defaults.fieldhandle_class;
12839         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12840                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12841                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12842                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12843                 MonoMethod *method;
12844
12845                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12846                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12847                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12848                         method = ((MonoReflectionMethod *)c->cb)->method;
12849                 else
12850                         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)));
12851
12852                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12853                 *handle_class = mono_defaults.methodhandle_class;
12854                 mono_metadata_free_type (type);
12855         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12856                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12857                 if (m->method_args) {
12858                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12859                         if (context) {
12860                                 MonoError error;
12861                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12862                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12863                         }
12864                 } else {
12865                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12866                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12867                         MonoMethod *method;
12868
12869                         if (is_sre_method_builder (mono_object_class (m->mb)))
12870                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12871                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12872                                 method = ((MonoReflectionMethod *)m->mb)->method;
12873                         else
12874                                 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)));
12875
12876                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12877                         mono_metadata_free_type (type);
12878                 }
12879                 *handle_class = mono_defaults.methodhandle_class;
12880         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12881                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12882                 MonoType *mtype;
12883                 MonoClass *klass;
12884                 MonoMethod *method;
12885                 gpointer iter;
12886                 char *name;
12887
12888                 mtype = mono_reflection_type_get_handle (m->parent);
12889                 klass = mono_class_from_mono_type (mtype);
12890
12891                 /* Find the method */
12892
12893                 name = mono_string_to_utf8 (m->name);
12894                 iter = NULL;
12895                 while ((method = mono_class_get_methods (klass, &iter))) {
12896                         if (!strcmp (method->name, name))
12897                                 break;
12898                 }
12899                 g_free (name);
12900
12901                 // FIXME:
12902                 g_assert (method);
12903                 // FIXME: Check parameters/return value etc. match
12904
12905                 result = method;
12906                 *handle_class = mono_defaults.methodhandle_class;
12907         } else if (is_sre_array (mono_object_get_class(obj)) ||
12908                                 is_sre_byref (mono_object_get_class(obj)) ||
12909                                 is_sre_pointer (mono_object_get_class(obj))) {
12910                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12911                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12912
12913                 if (context) {
12914                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12915                         result = mono_class_from_mono_type (inflated);
12916                         mono_metadata_free_type (inflated);
12917                 } else {
12918                         result = mono_class_from_mono_type (type);
12919                 }
12920                 *handle_class = mono_defaults.typehandle_class;
12921         } else {
12922                 g_print ("%s\n", obj->vtable->klass->name);
12923                 g_assert_not_reached ();
12924         }
12925         return result;
12926 }
12927
12928 #else /* DISABLE_REFLECTION_EMIT */
12929
12930 MonoArray*
12931 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12932 {
12933         g_assert_not_reached ();
12934         return NULL;
12935 }
12936
12937 void
12938 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12939 {
12940         g_assert_not_reached ();
12941 }
12942
12943 void
12944 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12945 {
12946         g_assert_not_reached ();
12947 }
12948
12949 void
12950 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12951 {
12952         g_assert_not_reached ();
12953 }
12954
12955 void
12956 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12957 {
12958         g_assert_not_reached ();
12959 }
12960
12961 void
12962 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12963 {
12964         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12965 }
12966
12967 void
12968 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12969 {
12970         g_assert_not_reached ();
12971 }
12972
12973 void
12974 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12975 {
12976         g_assert_not_reached ();
12977 }
12978
12979 MonoReflectionModule *
12980 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12981 {
12982         g_assert_not_reached ();
12983         return NULL;
12984 }
12985
12986 guint32
12987 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12988 {
12989         g_assert_not_reached ();
12990         return 0;
12991 }
12992
12993 guint32
12994 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
12995 {
12996         g_assert_not_reached ();
12997         return 0;
12998 }
12999
13000 guint32
13001 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13002                                                  gboolean create_open_instance, gboolean register_token)
13003 {
13004         g_assert_not_reached ();
13005         return 0;
13006 }
13007
13008 void
13009 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13010 {
13011 }
13012
13013 void
13014 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13015 {
13016         g_assert_not_reached ();
13017 }
13018
13019 void
13020 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13021 {
13022         *overrides = NULL;
13023         *num_overrides = 0;
13024 }
13025
13026 MonoReflectionEvent *
13027 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13028 {
13029         g_assert_not_reached ();
13030         return NULL;
13031 }
13032
13033 MonoReflectionType*
13034 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13035 {
13036         g_assert_not_reached ();
13037         return NULL;
13038 }
13039
13040 void
13041 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13042 {
13043         g_assert_not_reached ();
13044 }
13045
13046 MonoArray *
13047 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13048 {
13049         g_assert_not_reached ();
13050         return NULL;
13051 }
13052
13053 MonoArray *
13054 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13055 {
13056         g_assert_not_reached ();
13057         return NULL;
13058 }
13059
13060 void 
13061 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13062 {
13063 }
13064
13065 gpointer
13066 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13067 {
13068         return NULL;
13069 }
13070
13071 MonoType*
13072 mono_reflection_type_get_handle (MonoReflectionType* ref)
13073 {
13074         if (!ref)
13075                 return NULL;
13076         return ref->type;
13077 }
13078
13079 void
13080 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13081 {
13082         g_assert_not_reached ();
13083 }
13084
13085 #endif /* DISABLE_REFLECTION_EMIT */
13086
13087 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13088 const static guint32 declsec_flags_map[] = {
13089         0x00000000,                                     /* empty */
13090         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13091         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13092         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13093         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13094         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13095         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13096         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13097         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13098         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13099         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13100         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13101         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13102         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13103         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13104         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13105         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13106         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13107         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13108 };
13109
13110 /*
13111  * Returns flags that includes all available security action associated to the handle.
13112  * @token: metadata token (either for a class or a method)
13113  * @image: image where resides the metadata.
13114  */
13115 static guint32
13116 mono_declsec_get_flags (MonoImage *image, guint32 token)
13117 {
13118         int index = mono_metadata_declsec_from_index (image, token);
13119         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13120         guint32 result = 0;
13121         guint32 action;
13122         int i;
13123
13124         /* HasSecurity can be present for other, not specially encoded, attributes,
13125            e.g. SuppressUnmanagedCodeSecurityAttribute */
13126         if (index < 0)
13127                 return 0;
13128
13129         for (i = index; i < t->rows; i++) {
13130                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13131
13132                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13133                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13134                         break;
13135
13136                 action = cols [MONO_DECL_SECURITY_ACTION];
13137                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13138                         result |= declsec_flags_map [action];
13139                 } else {
13140                         g_assert_not_reached ();
13141                 }
13142         }
13143         return result;
13144 }
13145
13146 /*
13147  * Get the security actions (in the form of flags) associated with the specified method.
13148  *
13149  * @method: The method for which we want the declarative security flags.
13150  * Return the declarative security flags for the method (only).
13151  *
13152  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13153  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13154  */
13155 guint32
13156 mono_declsec_flags_from_method (MonoMethod *method)
13157 {
13158         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13159                 /* FIXME: No cache (for the moment) */
13160                 guint32 idx = mono_method_get_index (method);
13161                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13162                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13163                 return mono_declsec_get_flags (method->klass->image, idx);
13164         }
13165         return 0;
13166 }
13167
13168 /*
13169  * Get the security actions (in the form of flags) associated with the specified class.
13170  *
13171  * @klass: The class for which we want the declarative security flags.
13172  * Return the declarative security flags for the class.
13173  *
13174  * Note: We cache the flags inside the MonoClass structure as this will get 
13175  *       called very often (at least for each method).
13176  */
13177 guint32
13178 mono_declsec_flags_from_class (MonoClass *klass)
13179 {
13180         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13181                 if (!klass->ext || !klass->ext->declsec_flags) {
13182                         guint32 idx;
13183
13184                         idx = mono_metadata_token_index (klass->type_token);
13185                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13186                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13187                         mono_loader_lock ();
13188                         mono_class_alloc_ext (klass);
13189                         mono_loader_unlock ();
13190                         /* we cache the flags on classes */
13191                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13192                 }
13193                 return klass->ext->declsec_flags;
13194         }
13195         return 0;
13196 }
13197
13198 /*
13199  * Get the security actions (in the form of flags) associated with the specified assembly.
13200  *
13201  * @assembly: The assembly for which we want the declarative security flags.
13202  * Return the declarative security flags for the assembly.
13203  */
13204 guint32
13205 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13206 {
13207         guint32 idx = 1; /* there is only one assembly */
13208         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13209         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13210         return mono_declsec_get_flags (assembly->image, idx);
13211 }
13212
13213
13214 /*
13215  * Fill actions for the specific index (which may either be an encoded class token or
13216  * an encoded method token) from the metadata image.
13217  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13218  */
13219 static MonoBoolean
13220 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13221         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13222 {
13223         MonoBoolean result = FALSE;
13224         MonoTableInfo *t;
13225         guint32 cols [MONO_DECL_SECURITY_SIZE];
13226         int index = mono_metadata_declsec_from_index (image, token);
13227         int i;
13228
13229         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13230         for (i = index; i < t->rows; i++) {
13231                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13232
13233                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13234                         return result;
13235
13236                 /* if present only replace (class) permissions with method permissions */
13237                 /* if empty accept either class or method permissions */
13238                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13239                         if (!actions->demand.blob) {
13240                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13241                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13242                                 actions->demand.blob = (char*) (blob + 2);
13243                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13244                                 result = TRUE;
13245                         }
13246                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13247                         if (!actions->noncasdemand.blob) {
13248                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13249                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13250                                 actions->noncasdemand.blob = (char*) (blob + 2);
13251                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13252                                 result = TRUE;
13253                         }
13254                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13255                         if (!actions->demandchoice.blob) {
13256                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13257                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13258                                 actions->demandchoice.blob = (char*) (blob + 2);
13259                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13260                                 result = TRUE;
13261                         }
13262                 }
13263         }
13264
13265         return result;
13266 }
13267
13268 static MonoBoolean
13269 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13270         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13271 {
13272         guint32 idx = mono_metadata_token_index (klass->type_token);
13273         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13274         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13275         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13276 }
13277
13278 static MonoBoolean
13279 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13280         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13281 {
13282         guint32 idx = mono_method_get_index (method);
13283         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13284         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13285         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13286 }
13287
13288 /*
13289  * Collect all actions (that requires to generate code in mini) assigned for
13290  * the specified method.
13291  * Note: Don't use the content of actions if the function return FALSE.
13292  */
13293 MonoBoolean
13294 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13295 {
13296         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13297                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13298         MonoBoolean result = FALSE;
13299         guint32 flags;
13300
13301         /* quick exit if no declarative security is present in the metadata */
13302         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13303                 return FALSE;
13304
13305         /* we want the original as the wrapper is "free" of the security informations */
13306         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13307                 method = mono_marshal_method_from_wrapper (method);
13308                 if (!method)
13309                         return FALSE;
13310         }
13311
13312         /* First we look for method-level attributes */
13313         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13314                 mono_class_init (method->klass);
13315                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13316
13317                 result = mono_declsec_get_method_demands_params (method, demands, 
13318                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13319         }
13320
13321         /* Here we use (or create) the class declarative cache to look for demands */
13322         flags = mono_declsec_flags_from_class (method->klass);
13323         if (flags & mask) {
13324                 if (!result) {
13325                         mono_class_init (method->klass);
13326                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13327                 }
13328                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13329                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13330         }
13331
13332         /* The boolean return value is used as a shortcut in case nothing needs to
13333            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13334         return result;
13335 }
13336
13337
13338 /*
13339  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13340  *
13341  * Note: Don't use the content of actions if the function return FALSE.
13342  */
13343 MonoBoolean
13344 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13345 {
13346         MonoBoolean result = FALSE;
13347         guint32 flags;
13348
13349         /* quick exit if no declarative security is present in the metadata */
13350         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13351                 return FALSE;
13352
13353         /* we want the original as the wrapper is "free" of the security informations */
13354         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13355                 method = mono_marshal_method_from_wrapper (method);
13356                 if (!method)
13357                         return FALSE;
13358         }
13359
13360         /* results are independant - zeroize both */
13361         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13362         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13363
13364         /* First we look for method-level attributes */
13365         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13366                 mono_class_init (method->klass);
13367
13368                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13369                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13370         }
13371
13372         /* Here we use (or create) the class declarative cache to look for demands */
13373         flags = mono_declsec_flags_from_class (method->klass);
13374         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13375                 mono_class_init (method->klass);
13376
13377                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13378                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13379         }
13380
13381         return result;
13382 }
13383
13384 /*
13385  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13386  *
13387  * @klass       The inherited class - this is the class that provides the security check (attributes)
13388  * @demans      
13389  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13390  * 
13391  * Note: Don't use the content of actions if the function return FALSE.
13392  */
13393 MonoBoolean
13394 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13395 {
13396         MonoBoolean result = FALSE;
13397         guint32 flags;
13398
13399         /* quick exit if no declarative security is present in the metadata */
13400         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13401                 return FALSE;
13402
13403         /* Here we use (or create) the class declarative cache to look for demands */
13404         flags = mono_declsec_flags_from_class (klass);
13405         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13406                 mono_class_init (klass);
13407                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13408
13409                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13410                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13411         }
13412
13413         return result;
13414 }
13415
13416 /*
13417  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13418  *
13419  * Note: Don't use the content of actions if the function return FALSE.
13420  */
13421 MonoBoolean
13422 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13423 {
13424         /* quick exit if no declarative security is present in the metadata */
13425         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13426                 return FALSE;
13427
13428         /* we want the original as the wrapper is "free" of the security informations */
13429         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13430                 method = mono_marshal_method_from_wrapper (method);
13431                 if (!method)
13432                         return FALSE;
13433         }
13434
13435         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13436                 mono_class_init (method->klass);
13437                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13438
13439                 return mono_declsec_get_method_demands_params (method, demands, 
13440                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13441         }
13442         return FALSE;
13443 }
13444
13445
13446 static MonoBoolean
13447 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13448 {
13449         guint32 cols [MONO_DECL_SECURITY_SIZE];
13450         MonoTableInfo *t;
13451         int i;
13452
13453         int index = mono_metadata_declsec_from_index (image, token);
13454         if (index == -1)
13455                 return FALSE;
13456
13457         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13458         for (i = index; i < t->rows; i++) {
13459                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13460
13461                 /* shortcut - index are ordered */
13462                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13463                         return FALSE;
13464
13465                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13466                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13467                         entry->blob = (char*) (metadata + 2);
13468                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13469                         return TRUE;
13470                 }
13471         }
13472
13473         return FALSE;
13474 }
13475
13476 MonoBoolean
13477 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13478 {
13479         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13480                 guint32 idx = mono_method_get_index (method);
13481                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13482                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13483                 return get_declsec_action (method->klass->image, idx, action, entry);
13484         }
13485         return FALSE;
13486 }
13487
13488 MonoBoolean
13489 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13490 {
13491         /* use cache */
13492         guint32 flags = mono_declsec_flags_from_class (klass);
13493         if (declsec_flags_map [action] & flags) {
13494                 guint32 idx = mono_metadata_token_index (klass->type_token);
13495                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13496                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13497                 return get_declsec_action (klass->image, idx, action, entry);
13498         }
13499         return FALSE;
13500 }
13501
13502 MonoBoolean
13503 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13504 {
13505         guint32 idx = 1; /* there is only one assembly */
13506         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13507         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13508
13509         return get_declsec_action (assembly->image, idx, action, entry);
13510 }
13511
13512 gboolean
13513 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13514 {
13515         MonoError error;
13516         MonoObject *res, *exc;
13517         void *params [1];
13518         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13519         static MonoMethod *method = NULL;
13520
13521         if (!System_Reflection_Emit_TypeBuilder) {
13522                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13523                 g_assert (System_Reflection_Emit_TypeBuilder);
13524         }
13525         if (method == NULL) {
13526                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13527                 g_assert (method);
13528         }
13529
13530         /* 
13531          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13532          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13533          */
13534         g_assert (mono_class_get_ref_info (klass));
13535         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13536
13537         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13538         mono_error_raise_exception (&error); /* FIXME don't raise here */
13539
13540         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13541         if (exc)
13542                 return FALSE;
13543         else
13544                 return *(MonoBoolean*)mono_object_unbox (res);
13545 }
13546
13547 /**
13548  * mono_reflection_type_get_type:
13549  * @reftype: the System.Type object
13550  *
13551  * Returns the MonoType* associated with the C# System.Type object @reftype.
13552  */
13553 MonoType*
13554 mono_reflection_type_get_type (MonoReflectionType *reftype)
13555 {
13556         g_assert (reftype);
13557
13558         return mono_reflection_type_get_handle (reftype);
13559 }
13560
13561 /**
13562  * mono_reflection_assembly_get_assembly:
13563  * @refassembly: the System.Reflection.Assembly object
13564  *
13565  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13566  */
13567 MonoAssembly*
13568 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13569 {
13570         g_assert (refassembly);
13571
13572         return refassembly->assembly;
13573 }
13574