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