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