[runtime] mono_reflection_resolve_custom_attribute_data cleanup error handling
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void    ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
222 static GPtrArray *dynamic_images;
223 static mono_mutex_t dynamic_images_mutex;
224
225 static inline void
226 dynamic_images_lock (void)
227 {
228         mono_os_mutex_lock (&dynamic_images_mutex);
229 }
230
231 static inline void
232 dynamic_images_unlock (void)
233 {
234         mono_os_mutex_unlock (&dynamic_images_mutex);
235 }
236
237 /**
238  * mono_find_dynamic_image_owner:
239  *
240  * Find the dynamic image, if any, which a given pointer is located in the memory of.
241  */
242 MonoImage *
243 mono_find_dynamic_image_owner (void *ptr)
244 {
245         MonoImage *owner = NULL;
246         int i;
247
248         dynamic_images_lock ();
249
250         if (dynamic_images)
251         {
252                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
253                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
254                         if (mono_mempool_contains_addr (image->mempool, ptr))
255                                 owner = image;
256                 }
257         }
258
259         dynamic_images_unlock ();
260
261         return owner;
262 }
263
264 void
265 mono_reflection_init (void)
266 {
267         mono_os_mutex_init (&dynamic_images_mutex);
268 }
269
270 static inline void
271 dynamic_image_lock (MonoDynamicImage *image)
272 {
273         MONO_PREPARE_BLOCKING;
274         mono_image_lock ((MonoImage*)image);
275         MONO_FINISH_BLOCKING;
276 }
277
278 static inline void
279 dynamic_image_unlock (MonoDynamicImage *image)
280 {
281         mono_image_unlock ((MonoImage*)image);
282 }
283
284 static void
285 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
286 {
287         MONO_REQ_GC_UNSAFE_MODE;
288
289         dynamic_image_lock (assembly);
290         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
291         dynamic_image_unlock (assembly);
292 }
293
294 static MonoObject*
295 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
296 {
297         MONO_REQ_GC_UNSAFE_MODE;
298
299         MonoObject *obj;
300
301         dynamic_image_lock (assembly);
302         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
303         dynamic_image_unlock (assembly);
304
305         return obj;
306 }
307
308 static void
309 sigbuffer_init (SigBuffer *buf, int size)
310 {
311         MONO_REQ_GC_NEUTRAL_MODE;
312
313         buf->buf = (char *)g_malloc (size);
314         buf->p = buf->buf;
315         buf->end = buf->buf + size;
316 }
317
318 static void
319 sigbuffer_make_room (SigBuffer *buf, int size)
320 {
321         MONO_REQ_GC_NEUTRAL_MODE;
322
323         if (buf->end - buf->p < size) {
324                 int new_size = buf->end - buf->buf + size + 32;
325                 char *p = (char *)g_realloc (buf->buf, new_size);
326                 size = buf->p - buf->buf;
327                 buf->buf = p;
328                 buf->p = p + size;
329                 buf->end = buf->buf + new_size;
330         }
331 }
332
333 static void
334 sigbuffer_add_value (SigBuffer *buf, guint32 val)
335 {
336         MONO_REQ_GC_NEUTRAL_MODE;
337
338         sigbuffer_make_room (buf, 6);
339         mono_metadata_encode_value (val, buf->p, &buf->p);
340 }
341
342 static void
343 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
344 {
345         MONO_REQ_GC_NEUTRAL_MODE;
346
347         sigbuffer_make_room (buf, 1);
348         buf->p [0] = val;
349         buf->p++;
350 }
351
352 static void
353 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
354 {
355         MONO_REQ_GC_NEUTRAL_MODE;
356
357         sigbuffer_make_room (buf, size);
358         memcpy (buf->p, p, size);
359         buf->p += size;
360 }
361
362 static void
363 sigbuffer_free (SigBuffer *buf)
364 {
365         MONO_REQ_GC_NEUTRAL_MODE;
366
367         g_free (buf->buf);
368 }
369
370 #ifndef DISABLE_REFLECTION_EMIT
371 /**
372  * mp_g_alloc:
373  *
374  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
375  * from the C heap.
376  */
377 static gpointer
378 image_g_malloc (MonoImage *image, guint size)
379 {
380         MONO_REQ_GC_NEUTRAL_MODE;
381
382         if (image)
383                 return mono_image_alloc (image, size);
384         else
385                 return g_malloc (size);
386 }
387 #endif /* !DISABLE_REFLECTION_EMIT */
388
389 /**
390  * image_g_alloc0:
391  *
392  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
393  * from the C heap.
394  */
395 static gpointer
396 image_g_malloc0 (MonoImage *image, guint size)
397 {
398         MONO_REQ_GC_NEUTRAL_MODE;
399
400         if (image)
401                 return mono_image_alloc0 (image, size);
402         else
403                 return g_malloc0 (size);
404 }
405
406 #ifndef DISABLE_REFLECTION_EMIT
407 static char*
408 image_strdup (MonoImage *image, const char *s)
409 {
410         MONO_REQ_GC_NEUTRAL_MODE;
411
412         if (image)
413                 return mono_image_strdup (image, s);
414         else
415                 return g_strdup (s);
416 }
417 #endif
418
419 #define image_g_new(image,struct_type, n_structs)               \
420     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
421
422 #define image_g_new0(image,struct_type, n_structs)              \
423     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
424
425
426 static void
427 alloc_table (MonoDynamicTable *table, guint nrows)
428 {
429         MONO_REQ_GC_NEUTRAL_MODE;
430
431         table->rows = nrows;
432         g_assert (table->columns);
433         if (nrows + 1 >= table->alloc_rows) {
434                 while (nrows + 1 >= table->alloc_rows) {
435                         if (table->alloc_rows == 0)
436                                 table->alloc_rows = 16;
437                         else
438                                 table->alloc_rows *= 2;
439                 }
440
441                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
442         }
443 }
444
445 static void
446 make_room_in_stream (MonoDynamicStream *stream, int size)
447 {
448         MONO_REQ_GC_NEUTRAL_MODE;
449
450         if (size <= stream->alloc_size)
451                 return;
452         
453         while (stream->alloc_size <= size) {
454                 if (stream->alloc_size < 4096)
455                         stream->alloc_size = 4096;
456                 else
457                         stream->alloc_size *= 2;
458         }
459         
460         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
461 }
462
463 static guint32
464 string_heap_insert (MonoDynamicStream *sh, const char *str)
465 {
466         MONO_REQ_GC_NEUTRAL_MODE;
467
468         guint32 idx;
469         guint32 len;
470         gpointer oldkey, oldval;
471
472         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
473                 return GPOINTER_TO_UINT (oldval);
474
475         len = strlen (str) + 1;
476         idx = sh->index;
477         
478         make_room_in_stream (sh, idx + len);
479
480         /*
481          * We strdup the string even if we already copy them in sh->data
482          * so that the string pointers in the hash remain valid even if
483          * we need to realloc sh->data. We may want to avoid that later.
484          */
485         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
486         memcpy (sh->data + idx, str, len);
487         sh->index += len;
488         return idx;
489 }
490
491 static guint32
492 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
493 {
494         MONO_REQ_GC_UNSAFE_MODE;
495
496         char *name = mono_string_to_utf8 (str);
497         guint32 idx;
498         idx = string_heap_insert (sh, name);
499         g_free (name);
500         return idx;
501 }
502
503 #ifndef DISABLE_REFLECTION_EMIT
504 static void
505 string_heap_init (MonoDynamicStream *sh)
506 {
507         MONO_REQ_GC_NEUTRAL_MODE;
508
509         sh->index = 0;
510         sh->alloc_size = 4096;
511         sh->data = (char *)g_malloc (4096);
512         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
513         string_heap_insert (sh, "");
514 }
515 #endif
516
517 static guint32
518 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
519 {
520         MONO_REQ_GC_NEUTRAL_MODE;
521
522         guint32 idx;
523         
524         make_room_in_stream (stream, stream->index + len);
525         memcpy (stream->data + stream->index, data, len);
526         idx = stream->index;
527         stream->index += len;
528         /* 
529          * align index? Not without adding an additional param that controls it since
530          * we may store a blob value in pieces.
531          */
532         return idx;
533 }
534
535 static guint32
536 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
537 {
538         MONO_REQ_GC_NEUTRAL_MODE;
539
540         guint32 idx;
541         
542         make_room_in_stream (stream, stream->index + len);
543         memset (stream->data + stream->index, 0, len);
544         idx = stream->index;
545         stream->index += len;
546         return idx;
547 }
548
549 static void
550 stream_data_align (MonoDynamicStream *stream)
551 {
552         MONO_REQ_GC_NEUTRAL_MODE;
553
554         char buf [4] = {0};
555         guint32 count = stream->index % 4;
556
557         /* we assume the stream data will be aligned */
558         if (count)
559                 mono_image_add_stream_data (stream, buf, 4 - count);
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static int
564 mono_blob_entry_hash (const char* str)
565 {
566         MONO_REQ_GC_NEUTRAL_MODE;
567
568         guint len, h;
569         const char *end;
570         len = mono_metadata_decode_blob_size (str, &str);
571         if (len > 0) {
572                 end = str + len;
573                 h = *str;
574                 for (str += 1; str < end; str++)
575                         h = (h << 5) - h + *str;
576                 return h;
577         } else {
578                 return 0;
579         }
580 }
581
582 static gboolean
583 mono_blob_entry_equal (const char *str1, const char *str2) {
584         MONO_REQ_GC_NEUTRAL_MODE;
585
586         int len, len2;
587         const char *end1;
588         const char *end2;
589         len = mono_metadata_decode_blob_size (str1, &end1);
590         len2 = mono_metadata_decode_blob_size (str2, &end2);
591         if (len != len2)
592                 return 0;
593         return memcmp (end1, end2, len) == 0;
594 }
595 #endif
596 static guint32
597 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
598 {
599         MONO_REQ_GC_NEUTRAL_MODE;
600
601         guint32 idx;
602         char *copy;
603         gpointer oldkey, oldval;
604
605         copy = (char *)g_malloc (s1+s2);
606         memcpy (copy, b1, s1);
607         memcpy (copy + s1, b2, s2);
608         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
609                 g_free (copy);
610                 idx = GPOINTER_TO_UINT (oldval);
611         } else {
612                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
613                 mono_image_add_stream_data (&assembly->blob, b2, s2);
614                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
615         }
616         return idx;
617 }
618
619 static guint32
620 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
621 {
622         MONO_REQ_GC_NEUTRAL_MODE;
623
624         char blob_size [8];
625         char *b = blob_size;
626         guint32 size = buf->p - buf->buf;
627         /* store length */
628         g_assert (size <= (buf->end - buf->buf));
629         mono_metadata_encode_value (size, b, &b);
630         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
631 }
632
633 /*
634  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
635  * dest may be misaligned.
636  */
637 static void
638 swap_with_size (char *dest, const char* val, int len, int nelem) {
639         MONO_REQ_GC_NEUTRAL_MODE;
640 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
641         int elem;
642
643         for (elem = 0; elem < nelem; ++elem) {
644                 switch (len) {
645                 case 1:
646                         *dest = *val;
647                         break;
648                 case 2:
649                         dest [0] = val [1];
650                         dest [1] = val [0];
651                         break;
652                 case 4:
653                         dest [0] = val [3];
654                         dest [1] = val [2];
655                         dest [2] = val [1];
656                         dest [3] = val [0];
657                         break;
658                 case 8:
659                         dest [0] = val [7];
660                         dest [1] = val [6];
661                         dest [2] = val [5];
662                         dest [3] = val [4];
663                         dest [4] = val [3];
664                         dest [5] = val [2];
665                         dest [6] = val [1];
666                         dest [7] = val [0];
667                         break;
668                 default:
669                         g_assert_not_reached ();
670                 }
671                 dest += len;
672                 val += len;
673         }
674 #else
675         memcpy (dest, val, len * nelem);
676 #endif
677 }
678
679 static guint32
680 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
681 {
682         MONO_REQ_GC_UNSAFE_MODE;
683         
684         char blob_size [64];
685         char *b = blob_size;
686         guint32 idx = 0, len;
687
688         len = str->length * 2;
689         mono_metadata_encode_value (len, b, &b);
690 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
691         {
692                 char *swapped = g_malloc (2 * mono_string_length (str));
693                 const char *p = (const char*)mono_string_chars (str);
694
695                 swap_with_size (swapped, p, 2, mono_string_length (str));
696                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
697                 g_free (swapped);
698         }
699 #else
700         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
701 #endif
702         return idx;
703 }
704
705 #ifndef DISABLE_REFLECTION_EMIT
706 static MonoClass *
707 default_class_from_mono_type (MonoType *type)
708 {
709         MONO_REQ_GC_NEUTRAL_MODE;
710
711         switch (type->type) {
712         case MONO_TYPE_OBJECT:
713                 return mono_defaults.object_class;
714         case MONO_TYPE_VOID:
715                 return mono_defaults.void_class;
716         case MONO_TYPE_BOOLEAN:
717                 return mono_defaults.boolean_class;
718         case MONO_TYPE_CHAR:
719                 return mono_defaults.char_class;
720         case MONO_TYPE_I1:
721                 return mono_defaults.sbyte_class;
722         case MONO_TYPE_U1:
723                 return mono_defaults.byte_class;
724         case MONO_TYPE_I2:
725                 return mono_defaults.int16_class;
726         case MONO_TYPE_U2:
727                 return mono_defaults.uint16_class;
728         case MONO_TYPE_I4:
729                 return mono_defaults.int32_class;
730         case MONO_TYPE_U4:
731                 return mono_defaults.uint32_class;
732         case MONO_TYPE_I:
733                 return mono_defaults.int_class;
734         case MONO_TYPE_U:
735                 return mono_defaults.uint_class;
736         case MONO_TYPE_I8:
737                 return mono_defaults.int64_class;
738         case MONO_TYPE_U8:
739                 return mono_defaults.uint64_class;
740         case MONO_TYPE_R4:
741                 return mono_defaults.single_class;
742         case MONO_TYPE_R8:
743                 return mono_defaults.double_class;
744         case MONO_TYPE_STRING:
745                 return mono_defaults.string_class;
746         default:
747                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
748                 g_assert_not_reached ();
749         }
750         
751         return NULL;
752 }
753 #endif
754
755 /*
756  * mono_class_get_ref_info:
757  *
758  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
759  */
760 gpointer
761 mono_class_get_ref_info (MonoClass *klass)
762 {
763         MONO_REQ_GC_UNSAFE_MODE;
764
765         if (klass->ref_info_handle == 0)
766                 return NULL;
767         else
768                 return mono_gchandle_get_target (klass->ref_info_handle);
769 }
770
771 void
772 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
773 {
774         MONO_REQ_GC_UNSAFE_MODE;
775
776         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
777         g_assert (klass->ref_info_handle != 0);
778 }
779
780 void
781 mono_class_free_ref_info (MonoClass *klass)
782 {
783         MONO_REQ_GC_NEUTRAL_MODE;
784
785         if (klass->ref_info_handle) {
786                 mono_gchandle_free (klass->ref_info_handle);
787                 klass->ref_info_handle = 0;
788         }
789 }
790
791 static void
792 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
793 {
794         MONO_REQ_GC_NEUTRAL_MODE;
795
796         int i;
797         MonoGenericInst *class_inst;
798         MonoClass *klass;
799
800         g_assert (gclass);
801
802         class_inst = gclass->context.class_inst;
803
804         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
805         klass = gclass->container_class;
806         sigbuffer_add_value (buf, klass->byval_arg.type);
807         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
808
809         sigbuffer_add_value (buf, class_inst->type_argc);
810         for (i = 0; i < class_inst->type_argc; ++i)
811                 encode_type (assembly, class_inst->type_argv [i], buf);
812
813 }
814
815 static void
816 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (!type) {
821                 g_assert_not_reached ();
822                 return;
823         }
824                 
825         if (type->byref)
826                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
827
828         switch (type->type){
829         case MONO_TYPE_VOID:
830         case MONO_TYPE_BOOLEAN:
831         case MONO_TYPE_CHAR:
832         case MONO_TYPE_I1:
833         case MONO_TYPE_U1:
834         case MONO_TYPE_I2:
835         case MONO_TYPE_U2:
836         case MONO_TYPE_I4:
837         case MONO_TYPE_U4:
838         case MONO_TYPE_I8:
839         case MONO_TYPE_U8:
840         case MONO_TYPE_R4:
841         case MONO_TYPE_R8:
842         case MONO_TYPE_I:
843         case MONO_TYPE_U:
844         case MONO_TYPE_STRING:
845         case MONO_TYPE_OBJECT:
846         case MONO_TYPE_TYPEDBYREF:
847                 sigbuffer_add_value (buf, type->type);
848                 break;
849         case MONO_TYPE_PTR:
850                 sigbuffer_add_value (buf, type->type);
851                 encode_type (assembly, type->data.type, buf);
852                 break;
853         case MONO_TYPE_SZARRAY:
854                 sigbuffer_add_value (buf, type->type);
855                 encode_type (assembly, &type->data.klass->byval_arg, buf);
856                 break;
857         case MONO_TYPE_VALUETYPE:
858         case MONO_TYPE_CLASS: {
859                 MonoClass *k = mono_class_from_mono_type (type);
860
861                 if (k->generic_container) {
862                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
863                         encode_generic_class (assembly, gclass, buf);
864                 } else {
865                         /*
866                          * Make sure we use the correct type.
867                          */
868                         sigbuffer_add_value (buf, k->byval_arg.type);
869                         /*
870                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
871                          * otherwise two typerefs could point to the same type, leading to
872                          * verification errors.
873                          */
874                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
875                 }
876                 break;
877         }
878         case MONO_TYPE_ARRAY:
879                 sigbuffer_add_value (buf, type->type);
880                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
881                 sigbuffer_add_value (buf, type->data.array->rank);
882                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
883                 sigbuffer_add_value (buf, 0);
884                 break;
885         case MONO_TYPE_GENERICINST:
886                 encode_generic_class (assembly, type->data.generic_class, buf);
887                 break;
888         case MONO_TYPE_VAR:
889         case MONO_TYPE_MVAR:
890                 sigbuffer_add_value (buf, type->type);
891                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
892                 break;
893         default:
894                 g_error ("need to encode type %x", type->type);
895         }
896 }
897
898 static void
899 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
900 {
901         MONO_REQ_GC_UNSAFE_MODE;
902
903         if (!type) {
904                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
905                 return;
906         }
907
908         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
909 }
910
911 static void
912 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
913 {
914         MONO_REQ_GC_UNSAFE_MODE;
915
916         int i;
917
918         if (modreq) {
919                 for (i = 0; i < mono_array_length (modreq); ++i) {
920                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
921                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
922                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
923                 }
924         }
925         if (modopt) {
926                 for (i = 0; i < mono_array_length (modopt); ++i) {
927                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
928                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
929                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
930                 }
931         }
932 }
933
934 #ifndef DISABLE_REFLECTION_EMIT
935 static guint32
936 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
937 {
938         MONO_REQ_GC_UNSAFE_MODE;
939
940         SigBuffer buf;
941         int i;
942         guint32 nparams =  sig->param_count;
943         guint32 idx;
944
945         if (!assembly->save)
946                 return 0;
947
948         sigbuffer_init (&buf, 32);
949         /*
950          * FIXME: vararg, explicit_this, differenc call_conv values...
951          */
952         idx = sig->call_convention;
953         if (sig->hasthis)
954                 idx |= 0x20; /* hasthis */
955         if (sig->generic_param_count)
956                 idx |= 0x10; /* generic */
957         sigbuffer_add_byte (&buf, idx);
958         if (sig->generic_param_count)
959                 sigbuffer_add_value (&buf, sig->generic_param_count);
960         sigbuffer_add_value (&buf, nparams);
961         encode_type (assembly, sig->ret, &buf);
962         for (i = 0; i < nparams; ++i) {
963                 if (i == sig->sentinelpos)
964                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
965                 encode_type (assembly, sig->params [i], &buf);
966         }
967         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
968         sigbuffer_free (&buf);
969         return idx;
970 }
971 #endif
972
973 static guint32
974 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
975 {
976         MONO_REQ_GC_UNSAFE_MODE;
977
978         /*
979          * FIXME: reuse code from method_encode_signature().
980          */
981         SigBuffer buf;
982         int i;
983         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
984         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
985         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
986         guint32 idx;
987
988         sigbuffer_init (&buf, 32);
989         /* LAMESPEC: all the call conv spec is foobared */
990         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
991         if (mb->call_conv & 2)
992                 idx |= 0x5; /* vararg */
993         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
994                 idx |= 0x20; /* hasthis */
995         if (ngparams)
996                 idx |= 0x10; /* generic */
997         sigbuffer_add_byte (&buf, idx);
998         if (ngparams)
999                 sigbuffer_add_value (&buf, ngparams);
1000         sigbuffer_add_value (&buf, nparams + notypes);
1001         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1002         encode_reflection_type (assembly, mb->rtype, &buf);
1003         for (i = 0; i < nparams; ++i) {
1004                 MonoArray *modreq = NULL;
1005                 MonoArray *modopt = NULL;
1006                 MonoReflectionType *pt;
1007
1008                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1009                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1010                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1011                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1012                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1013                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1014                 encode_reflection_type (assembly, pt, &buf);
1015         }
1016         if (notypes)
1017                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1018         for (i = 0; i < notypes; ++i) {
1019                 MonoReflectionType *pt;
1020
1021                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1022                 encode_reflection_type (assembly, pt, &buf);
1023         }
1024
1025         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1026         sigbuffer_free (&buf);
1027         return idx;
1028 }
1029
1030 static guint32
1031 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1032 {
1033         MONO_REQ_GC_UNSAFE_MODE;
1034
1035         MonoDynamicTable *table;
1036         guint32 *values;
1037         guint32 idx, sig_idx;
1038         guint nl = mono_array_length (ilgen->locals);
1039         SigBuffer buf;
1040         int i;
1041
1042         sigbuffer_init (&buf, 32);
1043         sigbuffer_add_value (&buf, 0x07);
1044         sigbuffer_add_value (&buf, nl);
1045         for (i = 0; i < nl; ++i) {
1046                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1047                 
1048                 if (lb->is_pinned)
1049                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1050                 
1051                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1052         }
1053         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054         sigbuffer_free (&buf);
1055
1056         if (assembly->standalonesig_cache == NULL)
1057                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1058         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1059         if (idx)
1060                 return idx;
1061
1062         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1063         idx = table->next_idx ++;
1064         table->rows ++;
1065         alloc_table (table, table->rows);
1066         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1067
1068         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1069
1070         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1071
1072         return idx;
1073 }
1074
1075 static guint32
1076 method_count_clauses (MonoReflectionILGen *ilgen)
1077 {
1078         MONO_REQ_GC_UNSAFE_MODE;
1079
1080         guint32 num_clauses = 0;
1081         int i;
1082
1083         MonoILExceptionInfo *ex_info;
1084         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1085                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1086                 if (ex_info->handlers)
1087                         num_clauses += mono_array_length (ex_info->handlers);
1088                 else
1089                         num_clauses++;
1090         }
1091
1092         return num_clauses;
1093 }
1094
1095 #ifndef DISABLE_REFLECTION_EMIT
1096 static MonoExceptionClause*
1097 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1098 {
1099         MONO_REQ_GC_UNSAFE_MODE;
1100
1101         MonoExceptionClause *clauses;
1102         MonoExceptionClause *clause;
1103         MonoILExceptionInfo *ex_info;
1104         MonoILExceptionBlock *ex_block;
1105         guint32 finally_start;
1106         int i, j, clause_index;;
1107
1108         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1109
1110         clause_index = 0;
1111         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1112                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1113                 finally_start = ex_info->start + ex_info->len;
1114                 if (!ex_info->handlers)
1115                         continue;
1116                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1117                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1118                         clause = &(clauses [clause_index]);
1119
1120                         clause->flags = ex_block->type;
1121                         clause->try_offset = ex_info->start;
1122
1123                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1124                                 clause->try_len = finally_start - ex_info->start;
1125                         else
1126                                 clause->try_len = ex_info->len;
1127                         clause->handler_offset = ex_block->start;
1128                         clause->handler_len = ex_block->len;
1129                         if (ex_block->extype) {
1130                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1131                         } else {
1132                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1133                                         clause->data.filter_offset = ex_block->filter_offset;
1134                                 else
1135                                         clause->data.filter_offset = 0;
1136                         }
1137                         finally_start = ex_block->start + ex_block->len;
1138
1139                         clause_index ++;
1140                 }
1141         }
1142
1143         return clauses;
1144 }
1145 #endif /* !DISABLE_REFLECTION_EMIT */
1146
1147 static guint32
1148 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1149 {
1150         MONO_REQ_GC_UNSAFE_MODE;
1151
1152         char flags = 0;
1153         guint32 idx;
1154         guint32 code_size;
1155         gint32 max_stack, i;
1156         gint32 num_locals = 0;
1157         gint32 num_exception = 0;
1158         gint maybe_small;
1159         guint32 fat_flags;
1160         char fat_header [12];
1161         guint32 int_value;
1162         guint16 short_value;
1163         guint32 local_sig = 0;
1164         guint32 header_size = 12;
1165         MonoArray *code;
1166
1167         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1168                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1169                 return 0;
1170
1171         /*if (mb->name)
1172                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1173         if (mb->ilgen) {
1174                 code = mb->ilgen->code;
1175                 code_size = mb->ilgen->code_len;
1176                 max_stack = mb->ilgen->max_stack;
1177                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1178                 if (mb->ilgen->ex_handlers)
1179                         num_exception = method_count_clauses (mb->ilgen);
1180         } else {
1181                 code = mb->code;
1182                 if (code == NULL){
1183                         char *name = mono_string_to_utf8 (mb->name);
1184                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1185                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1186                         g_free (str);
1187                         g_free (name);
1188                         mono_raise_exception (exception);
1189                 }
1190
1191                 code_size = mono_array_length (code);
1192                 max_stack = 8; /* we probably need to run a verifier on the code... */
1193         }
1194
1195         stream_data_align (&assembly->code);
1196
1197         /* check for exceptions, maxstack, locals */
1198         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1199         if (maybe_small) {
1200                 if (code_size < 64 && !(code_size & 1)) {
1201                         flags = (code_size << 2) | 0x2;
1202                 } else if (code_size < 32 && (code_size & 1)) {
1203                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1204                 } else {
1205                         goto fat_header;
1206                 }
1207                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1208                 /* add to the fixup todo list */
1209                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1210                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1211                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1212                 return assembly->text_rva + idx;
1213         } 
1214 fat_header:
1215         if (num_locals)
1216                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1217         /* 
1218          * FIXME: need to set also the header size in fat_flags.
1219          * (and more sects and init locals flags)
1220          */
1221         fat_flags =  0x03;
1222         if (num_exception)
1223                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1224         if (mb->init_locals)
1225                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1226         fat_header [0] = fat_flags;
1227         fat_header [1] = (header_size / 4 ) << 4;
1228         short_value = GUINT16_TO_LE (max_stack);
1229         memcpy (fat_header + 2, &short_value, 2);
1230         int_value = GUINT32_TO_LE (code_size);
1231         memcpy (fat_header + 4, &int_value, 4);
1232         int_value = GUINT32_TO_LE (local_sig);
1233         memcpy (fat_header + 8, &int_value, 4);
1234         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1235         /* add to the fixup todo list */
1236         if (mb->ilgen && mb->ilgen->num_token_fixups)
1237                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1238         
1239         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1240         if (num_exception) {
1241                 unsigned char sheader [4];
1242                 MonoILExceptionInfo * ex_info;
1243                 MonoILExceptionBlock * ex_block;
1244                 int j;
1245
1246                 stream_data_align (&assembly->code);
1247                 /* always use fat format for now */
1248                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1249                 num_exception *= 6 * sizeof (guint32);
1250                 num_exception += 4; /* include the size of the header */
1251                 sheader [1] = num_exception & 0xff;
1252                 sheader [2] = (num_exception >> 8) & 0xff;
1253                 sheader [3] = (num_exception >> 16) & 0xff;
1254                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1255                 /* fat header, so we are already aligned */
1256                 /* reverse order */
1257                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1258                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1259                         if (ex_info->handlers) {
1260                                 int finally_start = ex_info->start + ex_info->len;
1261                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1262                                         guint32 val;
1263                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1264                                         /* the flags */
1265                                         val = GUINT32_TO_LE (ex_block->type);
1266                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1267                                         /* try offset */
1268                                         val = GUINT32_TO_LE (ex_info->start);
1269                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1270                                         /* need fault, too, probably */
1271                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1272                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1273                                         else
1274                                                 val = GUINT32_TO_LE (ex_info->len);
1275                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276                                         /* handler offset */
1277                                         val = GUINT32_TO_LE (ex_block->start);
1278                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1279                                         /* handler len */
1280                                         val = GUINT32_TO_LE (ex_block->len);
1281                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1282                                         finally_start = ex_block->start + ex_block->len;
1283                                         if (ex_block->extype) {
1284                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1285                                         } else {
1286                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1287                                                         val = ex_block->filter_offset;
1288                                                 else
1289                                                         val = 0;
1290                                         }
1291                                         val = GUINT32_TO_LE (val);
1292                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1293                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1294                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1295                                 }
1296                         } else {
1297                                 g_error ("No clauses for ex info block %d", i);
1298                         }
1299                 }
1300         }
1301         return assembly->text_rva + idx;
1302 }
1303
1304 static guint32
1305 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1306 {
1307         MONO_REQ_GC_NEUTRAL_MODE;
1308
1309         int i;
1310         MonoDynamicTable *table;
1311         guint32 *values;
1312         
1313         table = &assembly->tables [table_idx];
1314
1315         g_assert (col < table->columns);
1316
1317         values = table->values + table->columns;
1318         for (i = 1; i <= table->rows; ++i) {
1319                 if (values [col] == token)
1320                         return i;
1321                 values += table->columns;
1322         }
1323         return 0;
1324 }
1325
1326 /*
1327  * LOCKING: Acquires the loader lock. 
1328  */
1329 static MonoCustomAttrInfo*
1330 lookup_custom_attr (MonoImage *image, gpointer member)
1331 {
1332         MONO_REQ_GC_NEUTRAL_MODE;
1333
1334         MonoCustomAttrInfo* res;
1335
1336         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1337
1338         if (!res)
1339                 return NULL;
1340
1341         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1342         res->cached = 0;
1343         return res;
1344 }
1345
1346 static gboolean
1347 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1348 {
1349         MONO_REQ_GC_UNSAFE_MODE;
1350
1351         /* FIXME: Need to do more checks */
1352         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1353                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1354
1355                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1356                         return FALSE;
1357         }
1358
1359         return TRUE;
1360 }
1361
1362 static MonoCustomAttrInfo*
1363 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1364 {
1365         MONO_REQ_GC_UNSAFE_MODE;
1366
1367         int i, index, count, not_visible;
1368         MonoCustomAttrInfo *ainfo;
1369         MonoReflectionCustomAttr *cattr;
1370
1371         if (!cattrs)
1372                 return NULL;
1373         /* FIXME: check in assembly the Run flag is set */
1374
1375         count = mono_array_length (cattrs);
1376
1377         /* Skip nonpublic attributes since MS.NET seems to do the same */
1378         /* FIXME: This needs to be done more globally */
1379         not_visible = 0;
1380         for (i = 0; i < count; ++i) {
1381                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1382                 if (!custom_attr_visible (image, cattr))
1383                         not_visible ++;
1384         }
1385         count -= not_visible;
1386
1387         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1388
1389         ainfo->image = image;
1390         ainfo->num_attrs = count;
1391         ainfo->cached = alloc_img != NULL;
1392         index = 0;
1393         for (i = 0; i < count; ++i) {
1394                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1395                 if (custom_attr_visible (image, cattr)) {
1396                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1397                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1398                         ainfo->attrs [index].ctor = cattr->ctor->method;
1399                         ainfo->attrs [index].data = saved;
1400                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1401                         index ++;
1402                 }
1403         }
1404
1405         return ainfo;
1406 }
1407
1408 #ifndef DISABLE_REFLECTION_EMIT
1409 /*
1410  * LOCKING: Acquires the loader lock. 
1411  */
1412 static void
1413 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1414 {
1415         MONO_REQ_GC_UNSAFE_MODE;
1416
1417         MonoCustomAttrInfo *ainfo, *tmp;
1418
1419         if (!cattrs || !mono_array_length (cattrs))
1420                 return;
1421
1422         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1423
1424         mono_loader_lock ();
1425         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1426         if (tmp)
1427                 mono_custom_attrs_free (tmp);
1428         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1429         mono_loader_unlock ();
1430
1431 }
1432 #endif
1433
1434 void
1435 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1436 {
1437         MONO_REQ_GC_NEUTRAL_MODE;
1438
1439         if (!ainfo->cached)
1440                 g_free (ainfo);
1441 }
1442
1443 /*
1444  * idx is the table index of the object
1445  * type is one of MONO_CUSTOM_ATTR_*
1446  */
1447 static void
1448 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1449 {
1450         MONO_REQ_GC_UNSAFE_MODE;
1451
1452         MonoDynamicTable *table;
1453         MonoReflectionCustomAttr *cattr;
1454         guint32 *values;
1455         guint32 count, i, token;
1456         char blob_size [6];
1457         char *p = blob_size;
1458         
1459         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1460         if (!cattrs)
1461                 return;
1462         count = mono_array_length (cattrs);
1463         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1464         table->rows += count;
1465         alloc_table (table, table->rows);
1466         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1467         idx <<= MONO_CUSTOM_ATTR_BITS;
1468         idx |= type;
1469         for (i = 0; i < count; ++i) {
1470                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1472                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1473                 type = mono_metadata_token_index (token);
1474                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1475                 switch (mono_metadata_token_table (token)) {
1476                 case MONO_TABLE_METHOD:
1477                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1478                         /*
1479                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1480                          * method, not the one returned by mono_image_create_token ().
1481                          */
1482                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1483                         break;
1484                 case MONO_TABLE_MEMBERREF:
1485                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1486                         break;
1487                 default:
1488                         g_warning ("got wrong token in custom attr");
1489                         continue;
1490                 }
1491                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1492                 p = blob_size;
1493                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1494                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1495                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1496                 values += MONO_CUSTOM_ATTR_SIZE;
1497                 ++table->next_idx;
1498         }
1499 }
1500
1501 static void
1502 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1503 {
1504         MONO_REQ_GC_UNSAFE_MODE;
1505
1506         MonoDynamicTable *table;
1507         guint32 *values;
1508         guint32 count, i, idx;
1509         MonoReflectionPermissionSet *perm;
1510
1511         if (!permissions)
1512                 return;
1513
1514         count = mono_array_length (permissions);
1515         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1516         table->rows += count;
1517         alloc_table (table, table->rows);
1518
1519         for (i = 0; i < mono_array_length (permissions); ++i) {
1520                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1521
1522                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1523
1524                 idx = mono_metadata_token_index (parent_token);
1525                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1526                 switch (mono_metadata_token_table (parent_token)) {
1527                 case MONO_TABLE_TYPEDEF:
1528                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1529                         break;
1530                 case MONO_TABLE_METHOD:
1531                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1532                         break;
1533                 case MONO_TABLE_ASSEMBLY:
1534                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1535                         break;
1536                 default:
1537                         g_assert_not_reached ();
1538                 }
1539
1540                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1541                 values [MONO_DECL_SECURITY_PARENT] = idx;
1542                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1543
1544                 ++table->next_idx;
1545         }
1546 }
1547
1548 /*
1549  * Fill in the MethodDef and ParamDef tables for a method.
1550  * This is used for both normal methods and constructors.
1551  */
1552 static void
1553 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1554 {
1555         MONO_REQ_GC_UNSAFE_MODE;
1556
1557         MonoDynamicTable *table;
1558         guint32 *values;
1559         guint i, count;
1560
1561         /* room in this table is already allocated */
1562         table = &assembly->tables [MONO_TABLE_METHOD];
1563         *mb->table_idx = table->next_idx ++;
1564         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1565         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1566         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1567         values [MONO_METHOD_FLAGS] = mb->attrs;
1568         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1569         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1570         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1571         
1572         table = &assembly->tables [MONO_TABLE_PARAM];
1573         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1574
1575         mono_image_add_decl_security (assembly, 
1576                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1577
1578         if (mb->pinfo) {
1579                 MonoDynamicTable *mtable;
1580                 guint32 *mvalues;
1581                 
1582                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1583                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1584                 
1585                 count = 0;
1586                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1587                         if (mono_array_get (mb->pinfo, gpointer, i))
1588                                 count++;
1589                 }
1590                 table->rows += count;
1591                 alloc_table (table, table->rows);
1592                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1593                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1594                         MonoReflectionParamBuilder *pb;
1595                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1596                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1597                                 values [MONO_PARAM_SEQUENCE] = i;
1598                                 if (pb->name != NULL) {
1599                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1600                                 } else {
1601                                         values [MONO_PARAM_NAME] = 0;
1602                                 }
1603                                 values += MONO_PARAM_SIZE;
1604                                 if (pb->marshal_info) {
1605                                         mtable->rows++;
1606                                         alloc_table (mtable, mtable->rows);
1607                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1608                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1609                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1610                                 }
1611                                 pb->table_idx = table->next_idx++;
1612                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1613                                         guint32 field_type = 0;
1614                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1615                                         mtable->rows ++;
1616                                         alloc_table (mtable, mtable->rows);
1617                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1618                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1619                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1620                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1621                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1622                                 }
1623                         }
1624                 }
1625         }
1626 }
1627
1628 #ifndef DISABLE_REFLECTION_EMIT
1629 static void
1630 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1631 {
1632         MonoError error;
1633         MONO_REQ_GC_UNSAFE_MODE;
1634
1635         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1636
1637         rmb->ilgen = mb->ilgen;
1638         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, &error);
1639         mono_error_raise_exception (&error); /* FIXME don't raise here */
1640         rmb->parameters = mb->parameters;
1641         rmb->generic_params = mb->generic_params;
1642         rmb->generic_container = mb->generic_container;
1643         rmb->opt_types = NULL;
1644         rmb->pinfo = mb->pinfo;
1645         rmb->attrs = mb->attrs;
1646         rmb->iattrs = mb->iattrs;
1647         rmb->call_conv = mb->call_conv;
1648         rmb->code = mb->code;
1649         rmb->type = mb->type;
1650         rmb->name = mb->name;
1651         rmb->table_idx = &mb->table_idx;
1652         rmb->init_locals = mb->init_locals;
1653         rmb->skip_visibility = FALSE;
1654         rmb->return_modreq = mb->return_modreq;
1655         rmb->return_modopt = mb->return_modopt;
1656         rmb->param_modreq = mb->param_modreq;
1657         rmb->param_modopt = mb->param_modopt;
1658         rmb->permissions = mb->permissions;
1659         rmb->mhandle = mb->mhandle;
1660         rmb->nrefs = 0;
1661         rmb->refs = NULL;
1662
1663         if (mb->dll) {
1664                 rmb->charset = mb->charset;
1665                 rmb->extra_flags = mb->extra_flags;
1666                 rmb->native_cc = mb->native_cc;
1667                 rmb->dllentry = mb->dllentry;
1668                 rmb->dll = mb->dll;
1669         }
1670 }
1671
1672 static void
1673 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1674 {
1675         MONO_REQ_GC_UNSAFE_MODE;
1676
1677         MonoError error;
1678         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1679
1680         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1681
1682         rmb->ilgen = mb->ilgen;
1683         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, &error);
1684         mono_error_raise_exception (&error); /* FIXME don't raise here */
1685         rmb->parameters = mb->parameters;
1686         rmb->generic_params = NULL;
1687         rmb->generic_container = NULL;
1688         rmb->opt_types = NULL;
1689         rmb->pinfo = mb->pinfo;
1690         rmb->attrs = mb->attrs;
1691         rmb->iattrs = mb->iattrs;
1692         rmb->call_conv = mb->call_conv;
1693         rmb->code = NULL;
1694         rmb->type = mb->type;
1695         rmb->name = mono_string_new (mono_domain_get (), name);
1696         rmb->table_idx = &mb->table_idx;
1697         rmb->init_locals = mb->init_locals;
1698         rmb->skip_visibility = FALSE;
1699         rmb->return_modreq = NULL;
1700         rmb->return_modopt = NULL;
1701         rmb->param_modreq = mb->param_modreq;
1702         rmb->param_modopt = mb->param_modopt;
1703         rmb->permissions = mb->permissions;
1704         rmb->mhandle = mb->mhandle;
1705         rmb->nrefs = 0;
1706         rmb->refs = NULL;
1707 }
1708
1709 static void
1710 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1711 {
1712         MONO_REQ_GC_UNSAFE_MODE;
1713
1714         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1715
1716         rmb->ilgen = mb->ilgen;
1717         rmb->rtype = mb->rtype;
1718         rmb->parameters = mb->parameters;
1719         rmb->generic_params = NULL;
1720         rmb->generic_container = NULL;
1721         rmb->opt_types = NULL;
1722         rmb->pinfo = NULL;
1723         rmb->attrs = mb->attrs;
1724         rmb->iattrs = 0;
1725         rmb->call_conv = mb->call_conv;
1726         rmb->code = NULL;
1727         rmb->type = (MonoObject *) mb->owner;
1728         rmb->name = mb->name;
1729         rmb->table_idx = NULL;
1730         rmb->init_locals = mb->init_locals;
1731         rmb->skip_visibility = mb->skip_visibility;
1732         rmb->return_modreq = NULL;
1733         rmb->return_modopt = NULL;
1734         rmb->param_modreq = NULL;
1735         rmb->param_modopt = NULL;
1736         rmb->permissions = NULL;
1737         rmb->mhandle = mb->mhandle;
1738         rmb->nrefs = 0;
1739         rmb->refs = NULL;
1740 }       
1741 #endif
1742
1743 static void
1744 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1745 {
1746         MONO_REQ_GC_UNSAFE_MODE;
1747
1748         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1749         MonoDynamicTable *table;
1750         guint32 *values;
1751         guint32 tok;
1752         MonoReflectionMethod *m;
1753         int i;
1754
1755         if (!mb->override_methods)
1756                 return;
1757
1758         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1759                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1760
1761                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1762                 table->rows ++;
1763                 alloc_table (table, table->rows);
1764                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1765                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1766                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1767
1768                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1769                 switch (mono_metadata_token_table (tok)) {
1770                 case MONO_TABLE_MEMBERREF:
1771                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1772                         break;
1773                 case MONO_TABLE_METHOD:
1774                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1775                         break;
1776                 default:
1777                         g_assert_not_reached ();
1778                 }
1779                 values [MONO_METHODIMPL_DECLARATION] = tok;
1780         }
1781 }
1782
1783 #ifndef DISABLE_REFLECTION_EMIT
1784 static void
1785 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1786 {
1787         MONO_REQ_GC_UNSAFE_MODE;
1788
1789         MonoDynamicTable *table;
1790         guint32 *values;
1791         ReflectionMethodBuilder rmb;
1792         int i;
1793
1794         reflection_methodbuilder_from_method_builder (&rmb, mb);
1795
1796         mono_image_basic_method (&rmb, assembly);
1797         mb->table_idx = *rmb.table_idx;
1798
1799         if (mb->dll) { /* It's a P/Invoke method */
1800                 guint32 moduleref;
1801                 /* map CharSet values to on-disk values */
1802                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1803                 int extra_flags = mb->extra_flags;
1804                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1805                 table->rows ++;
1806                 alloc_table (table, table->rows);
1807                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1808                 
1809                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1810                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1811                 if (mb->dllentry)
1812                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1813                 else
1814                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1815                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1816                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1817                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1818                         table->rows ++;
1819                         alloc_table (table, table->rows);
1820                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1821                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1822                 }
1823         }
1824
1825         if (mb->generic_params) {
1826                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1827                 table->rows += mono_array_length (mb->generic_params);
1828                 alloc_table (table, table->rows);
1829                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1830                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1831
1832                         mono_image_get_generic_param_info (
1833                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1834                 }
1835         }
1836
1837 }
1838
1839 static void
1840 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1841 {
1842         MONO_REQ_GC_UNSAFE_MODE;
1843
1844         ReflectionMethodBuilder rmb;
1845
1846         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1847
1848         mono_image_basic_method (&rmb, assembly);
1849         mb->table_idx = *rmb.table_idx;
1850 }
1851 #endif
1852
1853 static char*
1854 type_get_fully_qualified_name (MonoType *type)
1855 {
1856         MONO_REQ_GC_NEUTRAL_MODE;
1857
1858         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1859 }
1860
1861 static char*
1862 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1863 {
1864         MONO_REQ_GC_UNSAFE_MODE;
1865
1866         MonoClass *klass;
1867         MonoAssembly *ta;
1868
1869         klass = mono_class_from_mono_type (type);
1870         if (!klass) 
1871                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1872         ta = klass->image->assembly;
1873         if (assembly_is_dynamic (ta) || (ta == ass)) {
1874                 if (klass->generic_class || klass->generic_container)
1875                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1876                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1877                 else
1878                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1879         }
1880
1881         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1882 }
1883
1884 #ifndef DISABLE_REFLECTION_EMIT
1885 /*field_image is the image to which the eventual custom mods have been encoded against*/
1886 static guint32
1887 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1888 {
1889         MONO_REQ_GC_NEUTRAL_MODE;
1890
1891         SigBuffer buf;
1892         guint32 idx, i, token;
1893
1894         if (!assembly->save)
1895                 return 0;
1896
1897         sigbuffer_init (&buf, 32);
1898         
1899         sigbuffer_add_value (&buf, 0x06);
1900         /* encode custom attributes before the type */
1901         if (type->num_mods) {
1902                 for (i = 0; i < type->num_mods; ++i) {
1903                         if (field_image) {
1904                                 MonoError error;
1905                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1906                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1907
1908                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1909                         } else {
1910                                 token = type->modifiers [i].token;
1911                         }
1912
1913                         if (type->modifiers [i].required)
1914                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1915                         else
1916                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1917
1918                         sigbuffer_add_value (&buf, token);
1919                 }
1920         }
1921         encode_type (assembly, type, &buf);
1922         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1923         sigbuffer_free (&buf);
1924         return idx;
1925 }
1926 #endif
1927
1928 static guint32
1929 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1930 {
1931         MONO_REQ_GC_UNSAFE_MODE;
1932
1933         SigBuffer buf;
1934         guint32 idx;
1935         guint32 typespec = 0;
1936         MonoType *type;
1937         MonoClass *klass;
1938
1939         init_type_builder_generics (fb->type);
1940
1941         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1942         klass = mono_class_from_mono_type (type);
1943
1944         sigbuffer_init (&buf, 32);
1945         
1946         sigbuffer_add_value (&buf, 0x06);
1947         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1948         /* encode custom attributes before the type */
1949
1950         if (klass->generic_container)
1951                 typespec = create_typespec (assembly, type);
1952
1953         if (typespec) {
1954                 MonoGenericClass *gclass;
1955                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1956                 encode_generic_class (assembly, gclass, &buf);
1957         } else {
1958                 encode_type (assembly, type, &buf);
1959         }
1960         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1961         sigbuffer_free (&buf);
1962         return idx;
1963 }
1964
1965 static guint32
1966 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1967 {
1968         MONO_REQ_GC_UNSAFE_MODE;
1969
1970         char blob_size [64];
1971         char *b = blob_size;
1972         char *box_val;
1973         char* buf;
1974         guint32 idx = 0, len = 0, dummy = 0;
1975
1976         buf = (char *)g_malloc (64);
1977         if (!val) {
1978                 *ret_type = MONO_TYPE_CLASS;
1979                 len = 4;
1980                 box_val = (char*)&dummy;
1981         } else {
1982                 box_val = ((char*)val) + sizeof (MonoObject);
1983                 *ret_type = val->vtable->klass->byval_arg.type;
1984         }
1985 handle_enum:
1986         switch (*ret_type) {
1987         case MONO_TYPE_BOOLEAN:
1988         case MONO_TYPE_U1:
1989         case MONO_TYPE_I1:
1990                 len = 1;
1991                 break;
1992         case MONO_TYPE_CHAR:
1993         case MONO_TYPE_U2:
1994         case MONO_TYPE_I2:
1995                 len = 2;
1996                 break;
1997         case MONO_TYPE_U4:
1998         case MONO_TYPE_I4:
1999         case MONO_TYPE_R4:
2000                 len = 4;
2001                 break;
2002         case MONO_TYPE_U8:
2003         case MONO_TYPE_I8:
2004                 len = 8;
2005                 break;
2006         case MONO_TYPE_R8:
2007                 len = 8;
2008                 break;
2009         case MONO_TYPE_VALUETYPE: {
2010                 MonoClass *klass = val->vtable->klass;
2011                 
2012                 if (klass->enumtype) {
2013                         *ret_type = mono_class_enum_basetype (klass)->type;
2014                         goto handle_enum;
2015                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2016                         len = 8;
2017                 } else 
2018                         g_error ("we can't encode valuetypes, we should have never reached this line");
2019                 break;
2020         }
2021         case MONO_TYPE_CLASS:
2022                 break;
2023         case MONO_TYPE_STRING: {
2024                 MonoString *str = (MonoString*)val;
2025                 /* there is no signature */
2026                 len = str->length * 2;
2027                 mono_metadata_encode_value (len, b, &b);
2028 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2029                 {
2030                         char *swapped = g_malloc (2 * mono_string_length (str));
2031                         const char *p = (const char*)mono_string_chars (str);
2032
2033                         swap_with_size (swapped, p, 2, mono_string_length (str));
2034                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2035                         g_free (swapped);
2036                 }
2037 #else
2038                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2039 #endif
2040
2041                 g_free (buf);
2042                 return idx;
2043         }
2044         case MONO_TYPE_GENERICINST:
2045                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2046                 goto handle_enum;
2047         default:
2048                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2049         }
2050
2051         /* there is no signature */
2052         mono_metadata_encode_value (len, b, &b);
2053 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2054         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2055         swap_with_size (blob_size, box_val, len, 1);
2056         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2057 #else
2058         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2059 #endif
2060
2061         g_free (buf);
2062         return idx;
2063 }
2064
2065 static guint32
2066 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2067 {
2068         MONO_REQ_GC_UNSAFE_MODE;
2069
2070         char *str;
2071         SigBuffer buf;
2072         guint32 idx, len;
2073
2074         sigbuffer_init (&buf, 32);
2075
2076         sigbuffer_add_value (&buf, minfo->type);
2077
2078         switch (minfo->type) {
2079         case MONO_NATIVE_BYVALTSTR:
2080         case MONO_NATIVE_BYVALARRAY:
2081                 sigbuffer_add_value (&buf, minfo->count);
2082                 break;
2083         case MONO_NATIVE_LPARRAY:
2084                 if (minfo->eltype || minfo->has_size) {
2085                         sigbuffer_add_value (&buf, minfo->eltype);
2086                         if (minfo->has_size) {
2087                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2088                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2089
2090                                 /* LAMESPEC: ElemMult is undocumented */
2091                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2092                         }
2093                 }
2094                 break;
2095         case MONO_NATIVE_SAFEARRAY:
2096                 if (minfo->eltype)
2097                         sigbuffer_add_value (&buf, minfo->eltype);
2098                 break;
2099         case MONO_NATIVE_CUSTOM:
2100                 if (minfo->guid) {
2101                         str = mono_string_to_utf8 (minfo->guid);
2102                         len = strlen (str);
2103                         sigbuffer_add_value (&buf, len);
2104                         sigbuffer_add_mem (&buf, str, len);
2105                         g_free (str);
2106                 } else {
2107                         sigbuffer_add_value (&buf, 0);
2108                 }
2109                 /* native type name */
2110                 sigbuffer_add_value (&buf, 0);
2111                 /* custom marshaler type name */
2112                 if (minfo->marshaltype || minfo->marshaltyperef) {
2113                         if (minfo->marshaltyperef)
2114                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2115                         else
2116                                 str = mono_string_to_utf8 (minfo->marshaltype);
2117                         len = strlen (str);
2118                         sigbuffer_add_value (&buf, len);
2119                         sigbuffer_add_mem (&buf, str, len);
2120                         g_free (str);
2121                 } else {
2122                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2123                         sigbuffer_add_value (&buf, 0);
2124                 }
2125                 if (minfo->mcookie) {
2126                         str = mono_string_to_utf8 (minfo->mcookie);
2127                         len = strlen (str);
2128                         sigbuffer_add_value (&buf, len);
2129                         sigbuffer_add_mem (&buf, str, len);
2130                         g_free (str);
2131                 } else {
2132                         sigbuffer_add_value (&buf, 0);
2133                 }
2134                 break;
2135         default:
2136                 break;
2137         }
2138         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2139         sigbuffer_free (&buf);
2140         return idx;
2141 }
2142
2143 static void
2144 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2145 {
2146         MONO_REQ_GC_UNSAFE_MODE;
2147
2148         MonoDynamicTable *table;
2149         guint32 *values;
2150
2151         /* maybe this fixup should be done in the C# code */
2152         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2153                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2154         table = &assembly->tables [MONO_TABLE_FIELD];
2155         fb->table_idx = table->next_idx ++;
2156         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2157         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2158         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2159         values [MONO_FIELD_FLAGS] = fb->attrs;
2160         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2161
2162         if (fb->offset != -1) {
2163                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2164                 table->rows ++;
2165                 alloc_table (table, table->rows);
2166                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2167                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2168                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2169         }
2170         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2171                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2172                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2173                 table->rows ++;
2174                 alloc_table (table, table->rows);
2175                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2176                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2177                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2178                 values [MONO_CONSTANT_TYPE] = field_type;
2179                 values [MONO_CONSTANT_PADDING] = 0;
2180         }
2181         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2182                 guint32 rva_idx;
2183                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2184                 table->rows ++;
2185                 alloc_table (table, table->rows);
2186                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2187                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2188                 /*
2189                  * We store it in the code section because it's simpler for now.
2190                  */
2191                 if (fb->rva_data) {
2192                         if (mono_array_length (fb->rva_data) >= 10)
2193                                 stream_data_align (&assembly->code);
2194                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2195                 } else
2196                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2197                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2198         }
2199         if (fb->marshal_info) {
2200                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2201                 table->rows ++;
2202                 alloc_table (table, table->rows);
2203                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2204                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2205                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2206         }
2207 }
2208
2209 static guint32
2210 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2211 {
2212         MONO_REQ_GC_UNSAFE_MODE;
2213
2214         SigBuffer buf;
2215         guint32 nparams = 0;
2216         MonoReflectionMethodBuilder *mb = fb->get_method;
2217         MonoReflectionMethodBuilder *smb = fb->set_method;
2218         guint32 idx, i;
2219
2220         if (mb && mb->parameters)
2221                 nparams = mono_array_length (mb->parameters);
2222         if (!mb && smb && smb->parameters)
2223                 nparams = mono_array_length (smb->parameters) - 1;
2224         sigbuffer_init (&buf, 32);
2225         if (fb->call_conv & 0x20)
2226                 sigbuffer_add_byte (&buf, 0x28);
2227         else
2228                 sigbuffer_add_byte (&buf, 0x08);
2229         sigbuffer_add_value (&buf, nparams);
2230         if (mb) {
2231                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2232                 for (i = 0; i < nparams; ++i) {
2233                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2234                         encode_reflection_type (assembly, pt, &buf);
2235                 }
2236         } else if (smb && smb->parameters) {
2237                 /* the property type is the last param */
2238                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2239                 for (i = 0; i < nparams; ++i) {
2240                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2241                         encode_reflection_type (assembly, pt, &buf);
2242                 }
2243         } else {
2244                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2245         }
2246
2247         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2248         sigbuffer_free (&buf);
2249         return idx;
2250 }
2251
2252 static void
2253 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2254 {
2255         MONO_REQ_GC_UNSAFE_MODE;
2256
2257         MonoDynamicTable *table;
2258         guint32 *values;
2259         guint num_methods = 0;
2260         guint32 semaidx;
2261
2262         /* 
2263          * we need to set things in the following tables:
2264          * PROPERTYMAP (info already filled in _get_type_info ())
2265          * PROPERTY    (rows already preallocated in _get_type_info ())
2266          * METHOD      (method info already done with the generic method code)
2267          * METHODSEMANTICS
2268          * CONSTANT
2269          */
2270         table = &assembly->tables [MONO_TABLE_PROPERTY];
2271         pb->table_idx = table->next_idx ++;
2272         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2273         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2274         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2275         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2276
2277         /* FIXME: we still don't handle 'other' methods */
2278         if (pb->get_method) num_methods ++;
2279         if (pb->set_method) num_methods ++;
2280
2281         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2282         table->rows += num_methods;
2283         alloc_table (table, table->rows);
2284
2285         if (pb->get_method) {
2286                 semaidx = table->next_idx ++;
2287                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2289                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2290                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2291         }
2292         if (pb->set_method) {
2293                 semaidx = table->next_idx ++;
2294                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2295                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2296                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2297                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2298         }
2299         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2300                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2301                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2302                 table->rows ++;
2303                 alloc_table (table, table->rows);
2304                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2305                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2306                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2307                 values [MONO_CONSTANT_TYPE] = field_type;
2308                 values [MONO_CONSTANT_PADDING] = 0;
2309         }
2310 }
2311
2312 static void
2313 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2314 {
2315         MONO_REQ_GC_UNSAFE_MODE;
2316
2317         MonoDynamicTable *table;
2318         guint32 *values;
2319         guint num_methods = 0;
2320         guint32 semaidx;
2321
2322         /* 
2323          * we need to set things in the following tables:
2324          * EVENTMAP (info already filled in _get_type_info ())
2325          * EVENT    (rows already preallocated in _get_type_info ())
2326          * METHOD      (method info already done with the generic method code)
2327          * METHODSEMANTICS
2328          */
2329         table = &assembly->tables [MONO_TABLE_EVENT];
2330         eb->table_idx = table->next_idx ++;
2331         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2332         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2333         values [MONO_EVENT_FLAGS] = eb->attrs;
2334         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2335
2336         /*
2337          * FIXME: we still don't handle 'other' methods 
2338          */
2339         if (eb->add_method) num_methods ++;
2340         if (eb->remove_method) num_methods ++;
2341         if (eb->raise_method) num_methods ++;
2342
2343         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2344         table->rows += num_methods;
2345         alloc_table (table, table->rows);
2346
2347         if (eb->add_method) {
2348                 semaidx = table->next_idx ++;
2349                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2351                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2352                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2353         }
2354         if (eb->remove_method) {
2355                 semaidx = table->next_idx ++;
2356                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2358                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2359                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2360         }
2361         if (eb->raise_method) {
2362                 semaidx = table->next_idx ++;
2363                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2364                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2365                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2366                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2367         }
2368 }
2369
2370 static void
2371 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2372 {
2373         MONO_REQ_GC_UNSAFE_MODE;
2374
2375         MonoDynamicTable *table;
2376         guint32 num_constraints, i;
2377         guint32 *values;
2378         guint32 table_idx;
2379
2380         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2381         num_constraints = gparam->iface_constraints ?
2382                 mono_array_length (gparam->iface_constraints) : 0;
2383         table->rows += num_constraints;
2384         if (gparam->base_type)
2385                 table->rows++;
2386         alloc_table (table, table->rows);
2387
2388         if (gparam->base_type) {
2389                 table_idx = table->next_idx ++;
2390                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2391
2392                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2393                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2394                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2395         }
2396
2397         for (i = 0; i < num_constraints; i++) {
2398                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2399                         gparam->iface_constraints, gpointer, i);
2400
2401                 table_idx = table->next_idx ++;
2402                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2403
2404                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2405                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2406                         assembly, mono_reflection_type_get_handle (constraint));
2407         }
2408 }
2409
2410 static void
2411 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2412 {
2413         MONO_REQ_GC_UNSAFE_MODE;
2414
2415         GenericParamTableEntry *entry;
2416
2417         /*
2418          * The GenericParam table must be sorted according to the `owner' field.
2419          * We need to do this sorting prior to writing the GenericParamConstraint
2420          * table, since we have to use the final GenericParam table indices there
2421          * and they must also be sorted.
2422          */
2423
2424         entry = g_new0 (GenericParamTableEntry, 1);
2425         entry->owner = owner;
2426         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2427         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2428         entry->gparam = gparam;
2429         
2430         g_ptr_array_add (assembly->gen_params, entry);
2431 }
2432
2433 static void
2434 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2435 {
2436         MONO_REQ_GC_UNSAFE_MODE;
2437
2438         MonoDynamicTable *table;
2439         MonoGenericParam *param;
2440         guint32 *values;
2441         guint32 table_idx;
2442
2443         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2444         table_idx = table->next_idx ++;
2445         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2446
2447         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2448
2449         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2450         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2451         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2452         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2453
2454         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2455
2456         encode_constraints (entry->gparam, table_idx, assembly);
2457 }
2458
2459 static guint32
2460 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2461 {
2462         MONO_REQ_GC_UNSAFE_MODE;
2463
2464         MonoDynamicTable *table;
2465         guint32 token;
2466         guint32 *values;
2467         guint32 cols [MONO_ASSEMBLY_SIZE];
2468         const char *pubkey;
2469         guint32 publen;
2470
2471         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2472                 return token;
2473
2474         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2475                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2476                 token = table->next_idx ++;
2477                 table->rows ++;
2478                 alloc_table (table, table->rows);
2479                 values = table->values + token * MONO_MODULEREF_SIZE;
2480                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2481
2482                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2483                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2484                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2485
2486                 return token;
2487         }
2488         
2489         if (assembly_is_dynamic (image->assembly))
2490                 /* FIXME: */
2491                 memset (cols, 0, sizeof (cols));
2492         else {
2493                 /* image->assembly->image is the manifest module */
2494                 image = image->assembly->image;
2495                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2496         }
2497
2498         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2499         token = table->next_idx ++;
2500         table->rows ++;
2501         alloc_table (table, table->rows);
2502         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2503         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2504         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2505         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2506         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2507         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2508         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2509         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2510         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2511
2512         if (strcmp ("", image->assembly->aname.culture)) {
2513                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2514                                 image->assembly->aname.culture);
2515         }
2516
2517         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2518                 guchar pubtoken [9];
2519                 pubtoken [0] = 8;
2520                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2521                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2522         } else {
2523                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2524         }
2525         token <<= MONO_RESOLUTION_SCOPE_BITS;
2526         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2527         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2528         return token;
2529 }
2530
2531 static guint32
2532 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2533 {
2534         MONO_REQ_GC_NEUTRAL_MODE;
2535
2536         MonoDynamicTable *table;
2537         guint32 *values;
2538         guint32 token;
2539         SigBuffer buf;
2540
2541         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2542                 return token;
2543
2544         sigbuffer_init (&buf, 32);
2545         switch (type->type) {
2546         case MONO_TYPE_FNPTR:
2547         case MONO_TYPE_PTR:
2548         case MONO_TYPE_SZARRAY:
2549         case MONO_TYPE_ARRAY:
2550         case MONO_TYPE_VAR:
2551         case MONO_TYPE_MVAR:
2552         case MONO_TYPE_GENERICINST:
2553                 encode_type (assembly, type, &buf);
2554                 break;
2555         case MONO_TYPE_CLASS:
2556         case MONO_TYPE_VALUETYPE: {
2557                 MonoClass *k = mono_class_from_mono_type (type);
2558                 if (!k || !k->generic_container) {
2559                         sigbuffer_free (&buf);
2560                         return 0;
2561                 }
2562                 encode_type (assembly, type, &buf);
2563                 break;
2564         }
2565         default:
2566                 sigbuffer_free (&buf);
2567                 return 0;
2568         }
2569
2570         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571         if (assembly->save) {
2572                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2573                 alloc_table (table, table->rows + 1);
2574                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575                 values [MONO_TYPESPEC_SIGNATURE] = token;
2576         }
2577         sigbuffer_free (&buf);
2578
2579         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2581         table->next_idx ++;
2582         return token;
2583 }
2584
2585 static guint32
2586 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2587 {
2588         MONO_REQ_GC_UNSAFE_MODE;
2589
2590         MonoDynamicTable *table;
2591         guint32 *values;
2592         guint32 token, scope, enclosing;
2593         MonoClass *klass;
2594
2595         /* if the type requires a typespec, we must try that first*/
2596         if (try_typespec && (token = create_typespec (assembly, type)))
2597                 return token;
2598         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2599         if (token)
2600                 return token;
2601         klass = mono_class_from_mono_type (type);
2602         if (!klass)
2603                 klass = mono_class_from_mono_type (type);
2604
2605         /*
2606          * If it's in the same module and not a generic type parameter:
2607          */
2608         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2609                         (type->type != MONO_TYPE_MVAR)) {
2610                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2611                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2612                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2613                 return token;
2614         }
2615
2616         if (klass->nested_in) {
2617                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2618                 /* get the typeref idx of the enclosing type */
2619                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2620                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2621         } else {
2622                 scope = resolution_scope_from_image (assembly, klass->image);
2623         }
2624         table = &assembly->tables [MONO_TABLE_TYPEREF];
2625         if (assembly->save) {
2626                 alloc_table (table, table->rows + 1);
2627                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2628                 values [MONO_TYPEREF_SCOPE] = scope;
2629                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2630                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2631         }
2632         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2633         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2634         table->next_idx ++;
2635         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2636         return token;
2637 }
2638
2639 /*
2640  * Despite the name, we handle also TypeSpec (with the above helper).
2641  */
2642 static guint32
2643 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2644 {
2645         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2646 }
2647
2648 #ifndef DISABLE_REFLECTION_EMIT
2649 static guint32
2650 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2651 {
2652         MONO_REQ_GC_NEUTRAL_MODE;
2653
2654         MonoDynamicTable *table;
2655         guint32 *values;
2656         guint32 token, pclass;
2657
2658         switch (parent & MONO_TYPEDEFORREF_MASK) {
2659         case MONO_TYPEDEFORREF_TYPEREF:
2660                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2661                 break;
2662         case MONO_TYPEDEFORREF_TYPESPEC:
2663                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2664                 break;
2665         case MONO_TYPEDEFORREF_TYPEDEF:
2666                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2667                 break;
2668         default:
2669                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2670                 return 0;
2671         }
2672         /* extract the index */
2673         parent >>= MONO_TYPEDEFORREF_BITS;
2674
2675         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2676
2677         if (assembly->save) {
2678                 alloc_table (table, table->rows + 1);
2679                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2680                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2681                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2682                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2683         }
2684
2685         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2686         table->next_idx ++;
2687
2688         return token;
2689 }
2690
2691 /*
2692  * Insert a memberef row into the metadata: the token that point to the memberref
2693  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2694  * mono_image_get_fieldref_token()).
2695  * The sig param is an index to an already built signature.
2696  */
2697 static guint32
2698 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2699 {
2700         MONO_REQ_GC_NEUTRAL_MODE;
2701
2702         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2703         return mono_image_add_memberef_row (assembly, parent, name, sig);
2704 }
2705
2706
2707 static guint32
2708 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2709 {
2710         MONO_REQ_GC_NEUTRAL_MODE;
2711
2712         guint32 token;
2713         MonoMethodSignature *sig;
2714         
2715         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2716
2717         if (create_typespec) {
2718                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2719                 if (token)
2720                         return token;
2721         } 
2722
2723         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2724         if (token && !create_typespec)
2725                 return token;
2726
2727         g_assert (!method->is_inflated);
2728         if (!token) {
2729                 /*
2730                  * A methodref signature can't contain an unmanaged calling convention.
2731                  */
2732                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2733                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2734                         sig->call_convention = MONO_CALL_DEFAULT;
2735                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2736                         method->name,  method_encode_signature (assembly, sig));
2737                 g_free (sig);
2738                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2739         }
2740
2741         if (create_typespec) {
2742                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2743                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2744                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2745
2746                 if (assembly->save) {
2747                         guint32 *values;
2748
2749                         alloc_table (table, table->rows + 1);
2750                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2751                         values [MONO_METHODSPEC_METHOD] = token;
2752                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2753                 }
2754
2755                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2756                 table->next_idx ++;
2757                 /*methodspec and memberef tokens are diferent, */
2758                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2759                 return token;
2760         }
2761         return token;
2762 }
2763
2764 static guint32
2765 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2766 {
2767         guint32 token, parent, sig;
2768         ReflectionMethodBuilder rmb;
2769         char *name;
2770         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2771         
2772         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2773         if (token)
2774                 return token;
2775
2776         name = mono_string_to_utf8 (method->name);
2777         reflection_methodbuilder_from_method_builder (&rmb, method);
2778
2779         /*
2780          * A methodref signature can't contain an unmanaged calling convention.
2781          * Since some flags are encoded as part of call_conv, we need to check against it.
2782         */
2783         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2784                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2785
2786         sig = method_builder_encode_signature (assembly, &rmb);
2787
2788         if (tb->generic_params)
2789                 parent = create_generic_typespec (assembly, tb);
2790         else
2791                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2792
2793         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2794
2795         g_free (name);
2796         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2797         return token;
2798 }
2799
2800 static guint32
2801 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2802                                      const gchar *name, guint32 sig)
2803 {
2804         MonoDynamicTable *table;
2805         guint32 token;
2806         guint32 *values;
2807         
2808         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2809
2810         if (assembly->save) {
2811                 alloc_table (table, table->rows + 1);
2812                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2813                 values [MONO_MEMBERREF_CLASS] = original;
2814                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2815                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2816         }
2817
2818         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2819         table->next_idx ++;
2820
2821         return token;
2822 }
2823
2824 static guint32
2825 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2826 {
2827         SigBuffer buf;
2828         int i;
2829         guint32 nparams = mono_array_length (mb->generic_params);
2830         guint32 idx;
2831
2832         if (!assembly->save)
2833                 return 0;
2834
2835         sigbuffer_init (&buf, 32);
2836
2837         sigbuffer_add_value (&buf, 0xa);
2838         sigbuffer_add_value (&buf, nparams);
2839
2840         for (i = 0; i < nparams; i++) {
2841                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2842                 sigbuffer_add_value (&buf, i);
2843         }
2844
2845         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2846         sigbuffer_free (&buf);
2847         return idx;
2848 }
2849
2850 static guint32
2851 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2852 {
2853         MonoDynamicTable *table;
2854         guint32 *values;
2855         guint32 token, mtoken = 0;
2856
2857         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2858         if (token)
2859                 return token;
2860
2861         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2862
2863         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2864         switch (mono_metadata_token_table (mtoken)) {
2865         case MONO_TABLE_MEMBERREF:
2866                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2867                 break;
2868         case MONO_TABLE_METHOD:
2869                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2870                 break;
2871         default:
2872                 g_assert_not_reached ();
2873         }
2874
2875         if (assembly->save) {
2876                 alloc_table (table, table->rows + 1);
2877                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2878                 values [MONO_METHODSPEC_METHOD] = mtoken;
2879                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2880         }
2881
2882         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2883         table->next_idx ++;
2884
2885         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2886         return token;
2887 }
2888
2889 static guint32
2890 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2891 {
2892         guint32 token;
2893
2894         if (mb->generic_params && create_methodspec) 
2895                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2896
2897         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2898         if (token)
2899                 return token;
2900
2901         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2902         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2903         return token;
2904 }
2905
2906 static guint32
2907 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2908 {
2909         guint32 token, parent, sig;
2910         ReflectionMethodBuilder rmb;
2911         char *name;
2912         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2913         
2914         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2915         if (token)
2916                 return token;
2917
2918         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2919
2920         if (tb->generic_params)
2921                 parent = create_generic_typespec (assembly, tb);
2922         else
2923                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2924         
2925         name = mono_string_to_utf8 (rmb.name);
2926         sig = method_builder_encode_signature (assembly, &rmb);
2927
2928         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2929
2930         g_free (name);
2931         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2932         return token;
2933 }
2934 #endif
2935
2936 static gboolean
2937 is_field_on_inst (MonoClassField *field)
2938 {
2939         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2940 }
2941
2942 /*
2943  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2944  */
2945 static MonoType*
2946 get_field_on_inst_generic_type (MonoClassField *field)
2947 {
2948         MonoClass *klass, *gtd;
2949         MonoDynamicGenericClass *dgclass;
2950         int field_index;
2951
2952         g_assert (is_field_on_inst (field));
2953
2954         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2955
2956         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2957                 field_index = field - dgclass->fields;
2958                 return dgclass->field_generic_types [field_index];              
2959         }
2960
2961         klass = field->parent;
2962         gtd = klass->generic_class->container_class;
2963
2964         if (field >= klass->fields && field - klass->fields < klass->field.count) {
2965                 field_index = field - klass->fields;
2966                 return gtd->fields [field_index].type;
2967         }
2968
2969         g_assert_not_reached ();
2970         return 0;
2971 }
2972
2973 #ifndef DISABLE_REFLECTION_EMIT
2974 static guint32
2975 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2976 {
2977         MonoType *type;
2978         guint32 token;
2979
2980         g_assert (field);
2981         g_assert (field->parent);
2982
2983         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2984         if (token)
2985                 return token;
2986
2987         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2988                 int index = field - field->parent->fields;
2989                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2990         } else {
2991                 if (is_field_on_inst (field))
2992                         type = get_field_on_inst_generic_type (field);
2993                 else
2994                         type = mono_field_get_type (field);
2995         }
2996         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2997                                                                                         mono_field_get_name (field),
2998                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2999         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3000         return token;
3001 }
3002
3003 static guint32
3004 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3005 {
3006         guint32 token;
3007         MonoClass *klass;
3008         MonoGenericClass *gclass;
3009         MonoType *type;
3010         char *name;
3011
3012         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3013         if (token)
3014                 return token;
3015         if (is_sre_field_builder (mono_object_class (f->fb))) {
3016                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3017                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3018                 klass = mono_class_from_mono_type (type);
3019                 gclass = type->data.generic_class;
3020                 g_assert (gclass->is_dynamic);
3021
3022                 name = mono_string_to_utf8 (fb->name);
3023                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3024                                                                                                 field_encode_signature (assembly, fb));
3025                 g_free (name);          
3026         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3027                 guint32 sig;
3028                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3029
3030                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3031                 klass = mono_class_from_mono_type (type);
3032
3033                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3034                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3035         } else {
3036                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3037                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3038         }
3039
3040         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3041         return token;
3042 }
3043
3044 static guint32
3045 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3046 {
3047         guint32 sig, token;
3048         MonoClass *klass;
3049         MonoGenericClass *gclass;
3050         MonoType *type;
3051
3052         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3053
3054         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3055         if (token)
3056                 return token;
3057
3058         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3059                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3060                 ReflectionMethodBuilder rmb;
3061                 char *name;
3062
3063                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3064                 klass = mono_class_from_mono_type (type);
3065
3066                 gclass = type->data.generic_class;
3067                 g_assert (gclass->is_dynamic);
3068
3069                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3070
3071                 name = mono_string_to_utf8 (rmb.name);
3072
3073                 sig = method_builder_encode_signature (assembly, &rmb);
3074
3075                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3076                 g_free (name);
3077         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3078                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3079
3080                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3081                 klass = mono_class_from_mono_type (type);
3082
3083                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3084                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3085         } else {
3086                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3087                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3088         }
3089
3090
3091         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3092         return token;
3093 }
3094
3095 static MonoMethod*
3096 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3097 {
3098         MonoError error;
3099         MonoClass *klass;
3100         MonoGenericContext tmp_context;
3101         MonoType **type_argv;
3102         MonoGenericInst *ginst;
3103         MonoMethod *method, *inflated;
3104         int count, i;
3105
3106         init_type_builder_generics ((MonoObject*)m->inst);
3107
3108         method = inflate_method (m->inst, (MonoObject*)m->mb);
3109
3110         klass = method->klass;
3111
3112         if (m->method_args == NULL)
3113                 return method;
3114
3115         if (method->is_inflated)
3116                 method = ((MonoMethodInflated *) method)->declaring;
3117
3118         count = mono_array_length (m->method_args);
3119
3120         type_argv = g_new0 (MonoType *, count);
3121         for (i = 0; i < count; i++) {
3122                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3123                 type_argv [i] = mono_reflection_type_get_handle (garg);
3124         }
3125         ginst = mono_metadata_get_generic_inst (count, type_argv);
3126         g_free (type_argv);
3127
3128         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3129         tmp_context.method_inst = ginst;
3130
3131         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3132         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3133         return inflated;
3134 }
3135
3136 static guint32
3137 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3138 {
3139         guint32 sig, token = 0;
3140         MonoType *type;
3141         MonoClass *klass;
3142
3143         if (m->method_args) {
3144                 MonoMethod *inflated;
3145
3146                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3147                 if (create_methodspec)
3148                         token = mono_image_get_methodspec_token (assembly, inflated);
3149                 else
3150                         token = mono_image_get_inflated_method_token (assembly, inflated);
3151                 return token;
3152         }
3153
3154         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3155         if (token)
3156                 return token;
3157
3158         if (is_sre_method_builder (mono_object_class (m->mb))) {
3159                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3160                 MonoGenericClass *gclass;
3161                 ReflectionMethodBuilder rmb;
3162                 char *name;
3163
3164                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3165                 klass = mono_class_from_mono_type (type);
3166                 gclass = type->data.generic_class;
3167                 g_assert (gclass->is_dynamic);
3168
3169                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3170
3171                 name = mono_string_to_utf8 (rmb.name);
3172
3173                 sig = method_builder_encode_signature (assembly, &rmb);
3174
3175                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3176                 g_free (name);          
3177         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3178                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3179
3180                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3181                 klass = mono_class_from_mono_type (type);
3182
3183                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3184                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3185         } else {
3186                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3187                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3188         }
3189
3190         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3191         return token;
3192 }
3193
3194 static guint32
3195 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3196 {
3197         SigBuffer buf;
3198         int i;
3199         guint32 nparams = context->method_inst->type_argc;
3200         guint32 idx;
3201
3202         if (!assembly->save)
3203                 return 0;
3204
3205         sigbuffer_init (&buf, 32);
3206         /*
3207          * FIXME: vararg, explicit_this, differenc call_conv values...
3208          */
3209         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3210         sigbuffer_add_value (&buf, nparams);
3211
3212         for (i = 0; i < nparams; i++)
3213                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3214
3215         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3216         sigbuffer_free (&buf);
3217         return idx;
3218 }
3219
3220 static guint32
3221 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3222 {
3223         MonoDynamicTable *table;
3224         guint32 *values;
3225         guint32 token, mtoken = 0, sig;
3226         MonoMethodInflated *imethod;
3227         MonoMethod *declaring;
3228
3229         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3230
3231         g_assert (method->is_inflated);
3232         imethod = (MonoMethodInflated *) method;
3233         declaring = imethod->declaring;
3234
3235         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3236         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3237
3238         if (!mono_method_signature (declaring)->generic_param_count)
3239                 return mtoken;
3240
3241         switch (mono_metadata_token_table (mtoken)) {
3242         case MONO_TABLE_MEMBERREF:
3243                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3244                 break;
3245         case MONO_TABLE_METHOD:
3246                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3247                 break;
3248         default:
3249                 g_assert_not_reached ();
3250         }
3251
3252         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3253
3254         if (assembly->save) {
3255                 alloc_table (table, table->rows + 1);
3256                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3257                 values [MONO_METHODSPEC_METHOD] = mtoken;
3258                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3259         }
3260
3261         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3262         table->next_idx ++;
3263
3264         return token;
3265 }
3266
3267 static guint32
3268 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3269 {
3270         MonoMethodInflated *imethod;
3271         guint32 token;
3272         
3273         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3274         if (token)
3275                 return token;
3276
3277         g_assert (method->is_inflated);
3278         imethod = (MonoMethodInflated *) method;
3279
3280         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3281                 token = method_encode_methodspec (assembly, method);
3282         } else {
3283                 guint32 sig = method_encode_signature (
3284                         assembly, mono_method_signature (imethod->declaring));
3285                 token = mono_image_get_memberref_token (
3286                         assembly, &method->klass->byval_arg, method->name, sig);
3287         }
3288
3289         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3290         return token;
3291 }
3292
3293 static guint32
3294 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3295 {
3296         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3297         guint32 sig, token;
3298
3299         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3300         token = mono_image_get_memberref_token (
3301                 assembly, &m->klass->byval_arg, m->name, sig);
3302
3303         return token;
3304 }
3305
3306 static guint32
3307 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3308 {
3309         MonoDynamicTable *table;
3310         MonoClass *klass;
3311         MonoType *type;
3312         guint32 *values;
3313         guint32 token;
3314         SigBuffer buf;
3315         int count, i;
3316
3317         /*
3318          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3319          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3320          * Because of this, we must not insert it into the `typeref' hash table.
3321          */
3322         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3323         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3324         if (token)
3325                 return token;
3326
3327         sigbuffer_init (&buf, 32);
3328
3329         g_assert (tb->generic_params);
3330         klass = mono_class_from_mono_type (type);
3331
3332         if (tb->generic_container)
3333                 mono_reflection_create_generic_class (tb);
3334
3335         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3336         g_assert (klass->generic_container);
3337         sigbuffer_add_value (&buf, klass->byval_arg.type);
3338         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3339
3340         count = mono_array_length (tb->generic_params);
3341         sigbuffer_add_value (&buf, count);
3342         for (i = 0; i < count; i++) {
3343                 MonoReflectionGenericParam *gparam;
3344
3345                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3346
3347                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3348         }
3349
3350         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3351
3352         if (assembly->save) {
3353                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3354                 alloc_table (table, table->rows + 1);
3355                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3356                 values [MONO_TYPESPEC_SIGNATURE] = token;
3357         }
3358         sigbuffer_free (&buf);
3359
3360         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3361         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3362         table->next_idx ++;
3363         return token;
3364 }
3365
3366 /*
3367  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3368  */
3369 static MonoType*
3370 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3371 {
3372         int i, count, len, pos;
3373         MonoType *t;
3374
3375         count = 0;
3376         if (modreq)
3377                 count += mono_array_length (modreq);
3378         if (modopt)
3379                 count += mono_array_length (modopt);
3380
3381         if (count == 0)
3382                 return mono_metadata_type_dup (NULL, type);
3383
3384         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3385         t = (MonoType *)g_malloc (len);
3386         memcpy (t, type, MONO_SIZEOF_TYPE);
3387
3388         t->num_mods = count;
3389         pos = 0;
3390         if (modreq) {
3391                 for (i = 0; i < mono_array_length (modreq); ++i) {
3392                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3393                         t->modifiers [pos].required = 1;
3394                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3395                         pos ++;
3396                 }
3397         }
3398         if (modopt) {
3399                 for (i = 0; i < mono_array_length (modopt); ++i) {
3400                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3401                         t->modifiers [pos].required = 0;
3402                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3403                         pos ++;
3404                 }
3405         }
3406
3407         return t;
3408 }
3409
3410 static void
3411 init_type_builder_generics (MonoObject *type)
3412 {
3413         MonoReflectionTypeBuilder *tb;
3414
3415         if (!is_sre_type_builder(mono_object_class (type)))
3416                 return;
3417         tb = (MonoReflectionTypeBuilder *)type;
3418
3419         if (tb && tb->generic_container)
3420                 mono_reflection_create_generic_class (tb);
3421 }
3422
3423 static guint32
3424 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3425 {
3426         MonoDynamicTable *table;
3427         MonoType *custom = NULL, *type;
3428         guint32 *values;
3429         guint32 token, pclass, parent, sig;
3430         gchar *name;
3431
3432         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3433         if (token)
3434                 return token;
3435
3436         /* FIXME: is this call necessary? */
3437         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3438         name = mono_string_to_utf8 (fb->name);
3439
3440         /*FIXME this is one more layer of ugliness due how types are created.*/
3441         init_type_builder_generics (fb->type);
3442
3443         /* fb->type does not include the custom modifiers */
3444         /* FIXME: We should do this in one place when a fieldbuilder is created */
3445         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3446         if (fb->modreq || fb->modopt)
3447                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3448
3449         sig = fieldref_encode_signature (assembly, NULL, type);
3450         g_free (custom);
3451
3452         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3453         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3454         
3455         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3456         parent >>= MONO_TYPEDEFORREF_BITS;
3457
3458         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3459
3460         if (assembly->save) {
3461                 alloc_table (table, table->rows + 1);
3462                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3463                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3464                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3465                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3466         }
3467
3468         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3469         table->next_idx ++;
3470         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3471         g_free (name);
3472         return token;
3473 }
3474
3475 static guint32
3476 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3477 {
3478         SigBuffer buf;
3479         guint32 nargs;
3480         guint32 i, idx;
3481
3482         if (!assembly->save)
3483                 return 0;
3484
3485         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3486         g_assert (helper->type == 2);
3487
3488         if (helper->arguments)
3489                 nargs = mono_array_length (helper->arguments);
3490         else
3491                 nargs = 0;
3492
3493         sigbuffer_init (&buf, 32);
3494
3495         /* Encode calling convention */
3496         /* Change Any to Standard */
3497         if ((helper->call_conv & 0x03) == 0x03)
3498                 helper->call_conv = 0x01;
3499         /* explicit_this implies has_this */
3500         if (helper->call_conv & 0x40)
3501                 helper->call_conv &= 0x20;
3502
3503         if (helper->call_conv == 0) { /* Unmanaged */
3504                 idx = helper->unmanaged_call_conv - 1;
3505         } else {
3506                 /* Managed */
3507                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3508                 if (helper->call_conv & 0x02) /* varargs */
3509                         idx += 0x05;
3510         }
3511
3512         sigbuffer_add_byte (&buf, idx);
3513         sigbuffer_add_value (&buf, nargs);
3514         encode_reflection_type (assembly, helper->return_type, &buf);
3515         for (i = 0; i < nargs; ++i) {
3516                 MonoArray *modreqs = NULL;
3517                 MonoArray *modopts = NULL;
3518                 MonoReflectionType *pt;
3519
3520                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3521                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3522                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3523                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3524
3525                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3526                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3527                 encode_reflection_type (assembly, pt, &buf);
3528         }
3529         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3530         sigbuffer_free (&buf);
3531
3532         return idx;
3533 }
3534
3535 static guint32 
3536 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3537 {
3538         guint32 idx;
3539         MonoDynamicTable *table;
3540         guint32 *values;
3541
3542         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3543         idx = table->next_idx ++;
3544         table->rows ++;
3545         alloc_table (table, table->rows);
3546         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3547
3548         values [MONO_STAND_ALONE_SIGNATURE] =
3549                 mono_reflection_encode_sighelper (assembly, helper);
3550
3551         return idx;
3552 }
3553
3554 static int
3555 reflection_cc_to_file (int call_conv) {
3556         switch (call_conv & 0x3) {
3557         case 0:
3558         case 1: return MONO_CALL_DEFAULT;
3559         case 2: return MONO_CALL_VARARG;
3560         default:
3561                 g_assert_not_reached ();
3562         }
3563         return 0;
3564 }
3565 #endif /* !DISABLE_REFLECTION_EMIT */
3566
3567 typedef struct {
3568         MonoType *parent;
3569         MonoMethodSignature *sig;
3570         char *name;
3571         guint32 token;
3572 } ArrayMethod;
3573
3574 #ifndef DISABLE_REFLECTION_EMIT
3575 static guint32
3576 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3577 {
3578         guint32 nparams, i;
3579         GList *tmp;
3580         char *name;
3581         MonoMethodSignature *sig;
3582         ArrayMethod *am;
3583         MonoType *mtype;
3584
3585         name = mono_string_to_utf8 (m->name);
3586         nparams = mono_array_length (m->parameters);
3587         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3588         sig->hasthis = 1;
3589         sig->sentinelpos = -1;
3590         sig->call_convention = reflection_cc_to_file (m->call_conv);
3591         sig->param_count = nparams;
3592         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3593         mtype = mono_reflection_type_get_handle (m->parent);
3594         for (i = 0; i < nparams; ++i)
3595                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3596
3597         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3598                 am = (ArrayMethod *)tmp->data;
3599                 if (strcmp (name, am->name) == 0 && 
3600                                 mono_metadata_type_equal (am->parent, mtype) &&
3601                                 mono_metadata_signature_equal (am->sig, sig)) {
3602                         g_free (name);
3603                         g_free (sig);
3604                         m->table_idx = am->token & 0xffffff;
3605                         return am->token;
3606                 }
3607         }
3608         am = g_new0 (ArrayMethod, 1);
3609         am->name = name;
3610         am->sig = sig;
3611         am->parent = mtype;
3612         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3613                 method_encode_signature (assembly, sig));
3614         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3615         m->table_idx = am->token & 0xffffff;
3616         return am->token;
3617 }
3618
3619 /*
3620  * Insert into the metadata tables all the info about the TypeBuilder tb.
3621  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3622  */
3623 static void
3624 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3625 {
3626         MonoDynamicTable *table;
3627         guint *values;
3628         int i, is_object = 0, is_system = 0;
3629         char *n;
3630
3631         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3632         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3633         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3634         n = mono_string_to_utf8 (tb->name);
3635         if (strcmp (n, "Object") == 0)
3636                 is_object++;
3637         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3638         g_free (n);
3639         n = mono_string_to_utf8 (tb->nspace);
3640         if (strcmp (n, "System") == 0)
3641                 is_system++;
3642         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3643         g_free (n);
3644         if (tb->parent && !(is_system && is_object) && 
3645                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3646                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3647         } else {
3648                 values [MONO_TYPEDEF_EXTENDS] = 0;
3649         }
3650         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3651         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3652
3653         /*
3654          * if we have explicitlayout or sequentiallayouts, output data in the
3655          * ClassLayout table.
3656          */
3657         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3658                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3659                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3660                 table->rows++;
3661                 alloc_table (table, table->rows);
3662                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3663                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3664                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3665                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3666         }
3667
3668         /* handle interfaces */
3669         if (tb->interfaces) {
3670                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3671                 i = table->rows;
3672                 table->rows += mono_array_length (tb->interfaces);
3673                 alloc_table (table, table->rows);
3674                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3675                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3676                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3677                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3678                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3679                         values += MONO_INTERFACEIMPL_SIZE;
3680                 }
3681         }
3682
3683         /* handle fields */
3684         if (tb->fields) {
3685                 table = &assembly->tables [MONO_TABLE_FIELD];
3686                 table->rows += tb->num_fields;
3687                 alloc_table (table, table->rows);
3688                 for (i = 0; i < tb->num_fields; ++i)
3689                         mono_image_get_field_info (
3690                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3691         }
3692
3693         /* handle constructors */
3694         if (tb->ctors) {
3695                 table = &assembly->tables [MONO_TABLE_METHOD];
3696                 table->rows += mono_array_length (tb->ctors);
3697                 alloc_table (table, table->rows);
3698                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3699                         mono_image_get_ctor_info (domain,
3700                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3701         }
3702
3703         /* handle methods */
3704         if (tb->methods) {
3705                 table = &assembly->tables [MONO_TABLE_METHOD];
3706                 table->rows += tb->num_methods;
3707                 alloc_table (table, table->rows);
3708                 for (i = 0; i < tb->num_methods; ++i)
3709                         mono_image_get_method_info (
3710                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3711         }
3712
3713         /* Do the same with properties etc.. */
3714         if (tb->events && mono_array_length (tb->events)) {
3715                 table = &assembly->tables [MONO_TABLE_EVENT];
3716                 table->rows += mono_array_length (tb->events);
3717                 alloc_table (table, table->rows);
3718                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3719                 table->rows ++;
3720                 alloc_table (table, table->rows);
3721                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3722                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3723                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3724                 for (i = 0; i < mono_array_length (tb->events); ++i)
3725                         mono_image_get_event_info (
3726                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3727         }
3728         if (tb->properties && mono_array_length (tb->properties)) {
3729                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3730                 table->rows += mono_array_length (tb->properties);
3731                 alloc_table (table, table->rows);
3732                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3733                 table->rows ++;
3734                 alloc_table (table, table->rows);
3735                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3736                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3737                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3738                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3739                         mono_image_get_property_info (
3740                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3741         }
3742
3743         /* handle generic parameters */
3744         if (tb->generic_params) {
3745                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3746                 table->rows += mono_array_length (tb->generic_params);
3747                 alloc_table (table, table->rows);
3748                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3749                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3750
3751                         mono_image_get_generic_param_info (
3752                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3753                 }
3754         }
3755
3756         mono_image_add_decl_security (assembly, 
3757                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3758
3759         if (tb->subtypes) {
3760                 MonoDynamicTable *ntable;
3761                 
3762                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3763                 ntable->rows += mono_array_length (tb->subtypes);
3764                 alloc_table (ntable, ntable->rows);
3765                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3766
3767                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3768                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3769
3770                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3771                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3772                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3773                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3774                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3775                                 ntable->next_idx, ntable->rows);*/
3776                         values += MONO_NESTED_CLASS_SIZE;
3777                         ntable->next_idx++;
3778                 }
3779         }
3780 }
3781 #endif
3782
3783 static void
3784 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3785 {
3786         int i;
3787
3788         mono_ptr_array_append (*types, type);
3789
3790         if (!type->subtypes)
3791                 return;
3792
3793         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3794                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3795                 collect_types (types, subtype);
3796         }
3797 }
3798
3799 static gint
3800 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3801 {
3802         if ((*type1)->table_idx < (*type2)->table_idx)
3803                 return -1;
3804         else
3805                 if ((*type1)->table_idx > (*type2)->table_idx)
3806                         return 1;
3807         else
3808                 return 0;
3809 }
3810
3811 static void
3812 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3813         int i;
3814
3815         if (!pinfo)
3816                 return;
3817         for (i = 0; i < mono_array_length (pinfo); ++i) {
3818                 MonoReflectionParamBuilder *pb;
3819                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3820                 if (!pb)
3821                         continue;
3822                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3823         }
3824 }
3825
3826 static void
3827 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3828         int i;
3829         
3830         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3831         if (tb->fields) {
3832                 for (i = 0; i < tb->num_fields; ++i) {
3833                         MonoReflectionFieldBuilder* fb;
3834                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3835                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3836                 }
3837         }
3838         if (tb->events) {
3839                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3840                         MonoReflectionEventBuilder* eb;
3841                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3842                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3843                 }
3844         }
3845         if (tb->properties) {
3846                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3847                         MonoReflectionPropertyBuilder* pb;
3848                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3849                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3850                 }
3851         }
3852         if (tb->ctors) {
3853                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3854                         MonoReflectionCtorBuilder* cb;
3855                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3856                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3857                         params_add_cattrs (assembly, cb->pinfo);
3858                 }
3859         }
3860
3861         if (tb->methods) {
3862                 for (i = 0; i < tb->num_methods; ++i) {
3863                         MonoReflectionMethodBuilder* mb;
3864                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3865                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3866                         params_add_cattrs (assembly, mb->pinfo);
3867                 }
3868         }
3869
3870         if (tb->subtypes) {
3871                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3872                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3873         }
3874 }
3875
3876 static void
3877 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3878 {
3879         int i;
3880         
3881         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3882
3883         if (moduleb->global_methods) {
3884                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3885                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3886                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3887                         params_add_cattrs (assembly, mb->pinfo);
3888                 }
3889         }
3890
3891         if (moduleb->global_fields) {
3892                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3893                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3894                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3895                 }
3896         }
3897         
3898         if (moduleb->types) {
3899                 for (i = 0; i < moduleb->num_types; ++i)
3900                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3901         }
3902 }
3903
3904 static void
3905 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3906 {
3907         MonoDynamicTable *table;
3908         guint32 *values;
3909         char blob_size [6];
3910         guchar hash [20];
3911         char *b = blob_size;
3912         char *dir, *path;
3913
3914         table = &assembly->tables [MONO_TABLE_FILE];
3915         table->rows++;
3916         alloc_table (table, table->rows);
3917         values = table->values + table->next_idx * MONO_FILE_SIZE;
3918         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3919         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3920         if (image_is_dynamic (module->image)) {
3921                 /* This depends on the fact that the main module is emitted last */
3922                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3923                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3924         } else {
3925                 dir = NULL;
3926                 path = g_strdup (module->image->name);
3927         }
3928         mono_sha1_get_digest_from_file (path, hash);
3929         g_free (dir);
3930         g_free (path);
3931         mono_metadata_encode_value (20, b, &b);
3932         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3933         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3934         table->next_idx ++;
3935 }
3936
3937 static void
3938 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3939 {
3940         MonoDynamicTable *table;
3941         int i;
3942
3943         table = &assembly->tables [MONO_TABLE_MODULE];
3944         mb->table_idx = table->next_idx ++;
3945         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3946         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3947         i /= 16;
3948         ++i;
3949         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3950         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3951         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3952         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3953 }
3954
3955 static guint32
3956 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3957         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3958 {
3959         MonoDynamicTable *table;
3960         guint32 *values;
3961         guint32 visib, res;
3962
3963         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3964         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3965                 return 0;
3966
3967         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3968         table->rows++;
3969         alloc_table (table, table->rows);
3970         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3971
3972         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3973         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3974         if (klass->nested_in)
3975                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3976         else
3977                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3978         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3979         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3980
3981         res = table->next_idx;
3982
3983         table->next_idx ++;
3984
3985         /* Emit nested types */
3986         if (klass->ext && klass->ext->nested_classes) {
3987                 GList *tmp;
3988
3989                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3990                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3991         }
3992
3993         return res;
3994 }
3995
3996 static void
3997 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3998         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3999 {
4000         MonoClass *klass;
4001         guint32 idx, i;
4002
4003         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4004
4005         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4006
4007         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4008                                                                                                    parent_index, assembly);
4009
4010         /* 
4011          * Emit nested types
4012          * We need to do this ourselves since klass->nested_classes is not set up.
4013          */
4014         if (tb->subtypes) {
4015                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4016                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4017         }
4018 }
4019
4020 static void
4021 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4022         guint32 module_index, MonoDynamicImage *assembly)
4023 {
4024         MonoImage *image = module->image;
4025         MonoTableInfo  *t;
4026         guint32 i;
4027
4028         t = &image->tables [MONO_TABLE_TYPEDEF];
4029
4030         for (i = 0; i < t->rows; ++i) {
4031                 MonoError error;
4032                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4033                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4034
4035                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4036                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4037         }
4038 }
4039
4040 static void
4041 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4042 {
4043         MonoDynamicTable *table;
4044         guint32 *values;
4045         guint32 scope, scope_idx, impl, current_idx;
4046         gboolean forwarder = TRUE;
4047         gpointer iter = NULL;
4048         MonoClass *nested;
4049
4050         if (klass->nested_in) {
4051                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4052                 forwarder = FALSE;
4053         } else {
4054                 scope = resolution_scope_from_image (assembly, klass->image);
4055                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4056                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4057                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4058         }
4059
4060         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4061
4062         table->rows++;
4063         alloc_table (table, table->rows);
4064         current_idx = table->next_idx;
4065         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4066
4067         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4068         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4069         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4070         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4071         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4072
4073         table->next_idx++;
4074
4075         while ((nested = mono_class_get_nested_types (klass, &iter)))
4076                 add_exported_type (assemblyb, assembly, nested, current_idx);
4077 }
4078
4079 static void
4080 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4081 {
4082         MonoClass *klass;
4083         int i;
4084
4085         if (!assemblyb->type_forwarders)
4086                 return;
4087
4088         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4089                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4090                 MonoType *type;
4091                 if (!t)
4092                         continue;
4093
4094                 type = mono_reflection_type_get_handle (t);
4095                 g_assert (type);
4096
4097                 klass = mono_class_from_mono_type (type);
4098
4099                 add_exported_type (assemblyb, assembly, klass, 0);
4100         }
4101 }
4102
4103 #define align_pointer(base,p)\
4104         do {\
4105                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4106                 if (__diff & 3)\
4107                         (p) += 4 - (__diff & 3);\
4108         } while (0)
4109
4110 static int
4111 compare_constants (const void *a, const void *b)
4112 {
4113         const guint32 *a_values = (const guint32 *)a;
4114         const guint32 *b_values = (const guint32 *)b;
4115         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4116 }
4117
4118 static int
4119 compare_semantics (const void *a, const void *b)
4120 {
4121         const guint32 *a_values = (const guint32 *)a;
4122         const guint32 *b_values = (const guint32 *)b;
4123         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4124         if (assoc)
4125                 return assoc;
4126         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4127 }
4128
4129 static int
4130 compare_custom_attrs (const void *a, const void *b)
4131 {
4132         const guint32 *a_values = (const guint32 *)a;
4133         const guint32 *b_values = (const guint32 *)b;
4134
4135         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4136 }
4137
4138 static int
4139 compare_field_marshal (const void *a, const void *b)
4140 {
4141         const guint32 *a_values = (const guint32 *)a;
4142         const guint32 *b_values = (const guint32 *)b;
4143
4144         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4145 }
4146
4147 static int
4148 compare_nested (const void *a, const void *b)
4149 {
4150         const guint32 *a_values = (const guint32 *)a;
4151         const guint32 *b_values = (const guint32 *)b;
4152
4153         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4154 }
4155
4156 static int
4157 compare_genericparam (const void *a, const void *b)
4158 {
4159         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4160         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4161
4162         if ((*b_entry)->owner == (*a_entry)->owner)
4163                 return 
4164                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4165                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4166         else
4167                 return (*a_entry)->owner - (*b_entry)->owner;
4168 }
4169
4170 static int
4171 compare_declsecurity_attrs (const void *a, const void *b)
4172 {
4173         const guint32 *a_values = (const guint32 *)a;
4174         const guint32 *b_values = (const guint32 *)b;
4175
4176         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4177 }
4178
4179 static int
4180 compare_interface_impl (const void *a, const void *b)
4181 {
4182         const guint32 *a_values = (const guint32 *)a;
4183         const guint32 *b_values = (const guint32 *)b;
4184
4185         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4186         if (klass)
4187                 return klass;
4188
4189         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4190 }
4191
4192 static void
4193 pad_heap (MonoDynamicStream *sh)
4194 {
4195         if (sh->index & 3) {
4196                 int sz = 4 - (sh->index & 3);
4197                 memset (sh->data + sh->index, 0, sz);
4198                 sh->index += sz;
4199         }
4200 }
4201
4202 struct StreamDesc {
4203         const char *name;
4204         MonoDynamicStream *stream;
4205 };
4206
4207 /*
4208  * build_compressed_metadata() fills in the blob of data that represents the 
4209  * raw metadata as it will be saved in the PE file. The five streams are output 
4210  * and the metadata tables are comnpressed from the guint32 array representation, 
4211  * to the compressed on-disk format.
4212  */
4213 static void
4214 build_compressed_metadata (MonoDynamicImage *assembly)
4215 {
4216         MonoDynamicTable *table;
4217         int i;
4218         guint64 valid_mask = 0;
4219         guint64 sorted_mask;
4220         guint32 heapt_size = 0;
4221         guint32 meta_size = 256; /* allow for header and other stuff */
4222         guint32 table_offset;
4223         guint32 ntables = 0;
4224         guint64 *int64val;
4225         guint32 *int32val;
4226         guint16 *int16val;
4227         MonoImage *meta;
4228         unsigned char *p;
4229         struct StreamDesc stream_desc [5];
4230
4231         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4232         for (i = 0; i < assembly->gen_params->len; i++){
4233                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4234                 write_generic_param_entry (assembly, entry);
4235         }
4236
4237         stream_desc [0].name  = "#~";
4238         stream_desc [0].stream = &assembly->tstream;
4239         stream_desc [1].name  = "#Strings";
4240         stream_desc [1].stream = &assembly->sheap;
4241         stream_desc [2].name  = "#US";
4242         stream_desc [2].stream = &assembly->us;
4243         stream_desc [3].name  = "#Blob";
4244         stream_desc [3].stream = &assembly->blob;
4245         stream_desc [4].name  = "#GUID";
4246         stream_desc [4].stream = &assembly->guid;
4247         
4248         /* tables that are sorted */
4249         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4250                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4251                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4252                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4253                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4254                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4255                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4256         
4257         /* Compute table sizes */
4258         /* the MonoImage has already been created in mono_image_basic_init() */
4259         meta = &assembly->image;
4260
4261         /* sizes should be multiple of 4 */
4262         pad_heap (&assembly->blob);
4263         pad_heap (&assembly->guid);
4264         pad_heap (&assembly->sheap);
4265         pad_heap (&assembly->us);
4266
4267         /* Setup the info used by compute_sizes () */
4268         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4269         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4270         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4271
4272         meta_size += assembly->blob.index;
4273         meta_size += assembly->guid.index;
4274         meta_size += assembly->sheap.index;
4275         meta_size += assembly->us.index;
4276
4277         for (i=0; i < MONO_TABLE_NUM; ++i)
4278                 meta->tables [i].rows = assembly->tables [i].rows;
4279         
4280         for (i = 0; i < MONO_TABLE_NUM; i++){
4281                 if (meta->tables [i].rows == 0)
4282                         continue;
4283                 valid_mask |= (guint64)1 << i;
4284                 ntables ++;
4285                 meta->tables [i].row_size = mono_metadata_compute_size (
4286                         meta, i, &meta->tables [i].size_bitfield);
4287                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4288         }
4289         heapt_size += 24; /* #~ header size */
4290         heapt_size += ntables * 4;
4291         /* make multiple of 4 */
4292         heapt_size += 3;
4293         heapt_size &= ~3;
4294         meta_size += heapt_size;
4295         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4296         p = (unsigned char*)meta->raw_metadata;
4297         /* the metadata signature */
4298         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4299         /* version numbers and 4 bytes reserved */
4300         int16val = (guint16*)p;
4301         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4302         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4303         p += 8;
4304         /* version string */
4305         int32val = (guint32*)p;
4306         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4307         p += 4;
4308         memcpy (p, meta->version, strlen (meta->version));
4309         p += GUINT32_FROM_LE (*int32val);
4310         align_pointer (meta->raw_metadata, p);
4311         int16val = (guint16*)p;
4312         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4313         *int16val = GUINT16_TO_LE (5); /* number of streams */
4314         p += 4;
4315
4316         /*
4317          * write the stream info.
4318          */
4319         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4320         table_offset += 3; table_offset &= ~3;
4321
4322         assembly->tstream.index = heapt_size;
4323         for (i = 0; i < 5; ++i) {
4324                 int32val = (guint32*)p;
4325                 stream_desc [i].stream->offset = table_offset;
4326                 *int32val++ = GUINT32_TO_LE (table_offset);
4327                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4328                 table_offset += GUINT32_FROM_LE (*int32val);
4329                 table_offset += 3; table_offset &= ~3;
4330                 p += 8;
4331                 strcpy ((char*)p, stream_desc [i].name);
4332                 p += strlen (stream_desc [i].name) + 1;
4333                 align_pointer (meta->raw_metadata, p);
4334         }
4335         /* 
4336          * now copy the data, the table stream header and contents goes first.
4337          */
4338         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4339         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4340         int32val = (guint32*)p;
4341         *int32val = GUINT32_TO_LE (0); /* reserved */
4342         p += 4;
4343
4344         *p++ = 2; /* version */
4345         *p++ = 0;
4346
4347         if (meta->idx_string_wide)
4348                 *p |= 0x01;
4349         if (meta->idx_guid_wide)
4350                 *p |= 0x02;
4351         if (meta->idx_blob_wide)
4352                 *p |= 0x04;
4353         ++p;
4354         *p++ = 1; /* reserved */
4355         int64val = (guint64*)p;
4356         *int64val++ = GUINT64_TO_LE (valid_mask);
4357         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4358         p += 16;
4359         int32val = (guint32*)p;
4360         for (i = 0; i < MONO_TABLE_NUM; i++){
4361                 if (meta->tables [i].rows == 0)
4362                         continue;
4363                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4364         }
4365         p = (unsigned char*)int32val;
4366
4367         /* sort the tables that still need sorting */
4368         table = &assembly->tables [MONO_TABLE_CONSTANT];
4369         if (table->rows)
4370                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4371         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4372         if (table->rows)
4373                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4374         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4375         if (table->rows)
4376                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4377         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4378         if (table->rows)
4379                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4380         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4381         if (table->rows)
4382                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4383         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4384         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4385         if (table->rows)
4386                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4387         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4388         if (table->rows)
4389                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4390
4391         /* compress the tables */
4392         for (i = 0; i < MONO_TABLE_NUM; i++){
4393                 int row, col;
4394                 guint32 *values;
4395                 guint32 bitfield = meta->tables [i].size_bitfield;
4396                 if (!meta->tables [i].rows)
4397                         continue;
4398                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4399                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4400                 meta->tables [i].base = (char*)p;
4401                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4402                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4403                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4404                                 switch (mono_metadata_table_size (bitfield, col)) {
4405                                 case 1:
4406                                         *p++ = values [col];
4407                                         break;
4408                                 case 2:
4409                                         *p++ = values [col] & 0xff;
4410                                         *p++ = (values [col] >> 8) & 0xff;
4411                                         break;
4412                                 case 4:
4413                                         *p++ = values [col] & 0xff;
4414                                         *p++ = (values [col] >> 8) & 0xff;
4415                                         *p++ = (values [col] >> 16) & 0xff;
4416                                         *p++ = (values [col] >> 24) & 0xff;
4417                                         break;
4418                                 default:
4419                                         g_assert_not_reached ();
4420                                 }
4421                         }
4422                 }
4423                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4424         }
4425         
4426         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4427         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4428         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4429         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4430         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4431
4432         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4433 }
4434
4435 /*
4436  * Some tables in metadata need to be sorted according to some criteria, but
4437  * when methods and fields are first created with reflection, they may be assigned a token
4438  * that doesn't correspond to the final token they will get assigned after the sorting.
4439  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4440  * with the reflection objects that represent them. Once all the tables are set up, the 
4441  * reflection objects will contains the correct table index. fixup_method() will fixup the
4442  * tokens for the method with ILGenerator @ilgen.
4443  */
4444 static void
4445 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4446 {
4447         guint32 code_idx = GPOINTER_TO_UINT (value);
4448         MonoReflectionILTokenInfo *iltoken;
4449         MonoReflectionFieldBuilder *field;
4450         MonoReflectionCtorBuilder *ctor;
4451         MonoReflectionMethodBuilder *method;
4452         MonoReflectionTypeBuilder *tb;
4453         MonoReflectionArrayMethod *am;
4454         guint32 i, idx = 0;
4455         unsigned char *target;
4456
4457         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4458                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4459                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4460                 switch (target [3]) {
4461                 case MONO_TABLE_FIELD:
4462                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4463                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4464                                 idx = field->table_idx;
4465                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4466                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4467                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4468                         } else {
4469                                 g_assert_not_reached ();
4470                         }
4471                         break;
4472                 case MONO_TABLE_METHOD:
4473                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4474                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4475                                 idx = method->table_idx;
4476                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4477                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4478                                 idx = ctor->table_idx;
4479                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4480                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4481                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4482                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4483                         } else {
4484                                 g_assert_not_reached ();
4485                         }
4486                         break;
4487                 case MONO_TABLE_TYPEDEF:
4488                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4489                                 g_assert_not_reached ();
4490                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4491                         idx = tb->table_idx;
4492                         break;
4493                 case MONO_TABLE_MEMBERREF:
4494                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4495                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4496                                 idx = am->table_idx;
4497                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4498                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4499                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4500                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4501                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4502                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4503                                 continue;
4504                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4505                                 continue;
4506                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4507                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4508                                 g_assert (is_field_on_inst (f));
4509                                 continue;
4510                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4511                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4512                                 continue;
4513                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4514                                 continue;
4515                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4516                                 continue;
4517                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4518                                 continue;
4519                         } else {
4520                                 g_assert_not_reached ();
4521                         }
4522                         break;
4523                 case MONO_TABLE_METHODSPEC:
4524                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4525                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4526                                 g_assert (mono_method_signature (m)->generic_param_count);
4527                                 continue;
4528                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4529                                 continue;
4530                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4531                                 continue;
4532                         } else {
4533                                 g_assert_not_reached ();
4534                         }
4535                         break;
4536                 default:
4537                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4538                 }
4539                 target [0] = idx & 0xff;
4540                 target [1] = (idx >> 8) & 0xff;
4541                 target [2] = (idx >> 16) & 0xff;
4542         }
4543 }
4544
4545 /*
4546  * fixup_cattrs:
4547  *
4548  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4549  * value is not known when the table is emitted.
4550  */
4551 static void
4552 fixup_cattrs (MonoDynamicImage *assembly)
4553 {
4554         MonoDynamicTable *table;
4555         guint32 *values;
4556         guint32 type, i, idx, token;
4557         MonoObject *ctor;
4558
4559         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4560
4561         for (i = 0; i < table->rows; ++i) {
4562                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4563
4564                 type = values [MONO_CUSTOM_ATTR_TYPE];
4565                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4566                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4567                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4568                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4569                         g_assert (ctor);
4570
4571                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4572                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4573                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4574                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4575                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4576                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4577                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4578                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4579                         }
4580                 }
4581         }
4582 }
4583
4584 static void
4585 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4586 {
4587         MonoDynamicTable *table;
4588         guint32 *values;
4589
4590         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4591         table->rows++;
4592         alloc_table (table, table->rows);
4593         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4594         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4595         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4596         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4597         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4598         table->next_idx++;
4599 }
4600
4601 static void
4602 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4603 {
4604         MonoDynamicTable *table;
4605         guint32 *values;
4606         char blob_size [6];
4607         guchar hash [20];
4608         char *b = blob_size;
4609         char *name, *sname;
4610         guint32 idx, offset;
4611
4612         if (rsrc->filename) {
4613                 name = mono_string_to_utf8 (rsrc->filename);
4614                 sname = g_path_get_basename (name);
4615         
4616                 table = &assembly->tables [MONO_TABLE_FILE];
4617                 table->rows++;
4618                 alloc_table (table, table->rows);
4619                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4620                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4621                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4622                 g_free (sname);
4623
4624                 mono_sha1_get_digest_from_file (name, hash);
4625                 mono_metadata_encode_value (20, b, &b);
4626                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4627                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4628                 g_free (name);
4629                 idx = table->next_idx++;
4630                 rsrc->offset = 0;
4631                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4632         } else {
4633                 char sizebuf [4];
4634                 char *data;
4635                 guint len;
4636                 if (rsrc->data) {
4637                         data = mono_array_addr (rsrc->data, char, 0);
4638                         len = mono_array_length (rsrc->data);
4639                 } else {
4640                         data = NULL;
4641                         len = 0;
4642                 }
4643                 offset = len;
4644                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4645                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4646                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4647                 mono_image_add_stream_data (&assembly->resources, data, len);
4648
4649                 if (!mb->is_main)
4650                         /* 
4651                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4652                          * the main module, but that needs to reference the FILE table
4653                          * which isn't emitted yet.
4654                          */
4655                         return;
4656                 else
4657                         idx = 0;
4658         }
4659
4660         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4661 }
4662
4663 static void
4664 set_version_from_string (MonoString *version, guint32 *values)
4665 {
4666         gchar *ver, *p, *str;
4667         guint32 i;
4668         
4669         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4670         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4671         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4672         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4673         if (!version)
4674                 return;
4675         ver = str = mono_string_to_utf8 (version);
4676         for (i = 0; i < 4; ++i) {
4677                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4678                 switch (*p) {
4679                 case '.':
4680                         p++;
4681                         break;
4682                 case '*':
4683                         /* handle Revision and Build */
4684                         p++;
4685                         break;
4686                 }
4687                 ver = p;
4688         }
4689         g_free (str);
4690 }
4691
4692 static guint32
4693 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4694         gsize len;
4695         guint32 token = 0;
4696         char blob_size [6];
4697         char *b = blob_size;
4698
4699         if (!pkey)
4700                 return token;
4701
4702         len = mono_array_length (pkey);
4703         mono_metadata_encode_value (len, b, &b);
4704         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4705         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4706
4707         assembly->public_key = (guint8 *)g_malloc (len);
4708         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4709         assembly->public_key_len = len;
4710
4711         /* Special case: check for ECMA key (16 bytes) */
4712         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4713                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4714                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4715         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4716                 /* minimum key size (in 2.0) is 384 bits */
4717                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4718         } else {
4719                 /* FIXME - verifier */
4720                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4721                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4722         }
4723         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4724
4725         return token;
4726 }
4727
4728 static void
4729 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4730 {
4731         MonoDynamicTable *table;
4732         MonoDynamicImage *assembly;
4733         MonoReflectionAssemblyBuilder *assemblyb;
4734         MonoDomain *domain;
4735         guint32 *values;
4736         int i;
4737         guint32 module_index;
4738
4739         assemblyb = moduleb->assemblyb;
4740         assembly = moduleb->dynamic_image;
4741         domain = mono_object_domain (assemblyb);
4742
4743         /* Emit ASSEMBLY table */
4744         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4745         alloc_table (table, 1);
4746         values = table->values + MONO_ASSEMBLY_SIZE;
4747         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4748         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4749         if (assemblyb->culture) {
4750                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4751         } else {
4752                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4753         }
4754         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4755         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4756         set_version_from_string (assemblyb->version, values);
4757
4758         /* Emit FILE + EXPORTED_TYPE table */
4759         module_index = 0;
4760         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4761                 int j;
4762                 MonoReflectionModuleBuilder *file_module = 
4763                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4764                 if (file_module != moduleb) {
4765                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4766                         module_index ++;
4767                         if (file_module->types) {
4768                                 for (j = 0; j < file_module->num_types; ++j) {
4769                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4770                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4771                                 }
4772                         }
4773                 }
4774         }
4775         if (assemblyb->loaded_modules) {
4776                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4777                         MonoReflectionModule *file_module = 
4778                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4779                         mono_image_fill_file_table (domain, file_module, assembly);
4780                         module_index ++;
4781                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4782                 }
4783         }
4784         if (assemblyb->type_forwarders)
4785                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4786
4787         /* Emit MANIFESTRESOURCE table */
4788         module_index = 0;
4789         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4790                 int j;
4791                 MonoReflectionModuleBuilder *file_module = 
4792                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4793                 /* The table for the main module is emitted later */
4794                 if (file_module != moduleb) {
4795                         module_index ++;
4796                         if (file_module->resources) {
4797                                 int len = mono_array_length (file_module->resources);
4798                                 for (j = 0; j < len; ++j) {
4799                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4800                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4801                                 }
4802                         }
4803                 }
4804         }               
4805 }
4806
4807 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4808
4809 /*
4810  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4811  * for the modulebuilder @moduleb.
4812  * At the end of the process, method and field tokens are fixed up and the 
4813  * on-disk compressed metadata representation is created.
4814  */
4815 void
4816 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4817 {
4818         MonoDynamicTable *table;
4819         MonoDynamicImage *assembly;
4820         MonoReflectionAssemblyBuilder *assemblyb;
4821         MonoDomain *domain;
4822         MonoPtrArray types;
4823         guint32 *values;
4824         int i, j;
4825
4826         assemblyb = moduleb->assemblyb;
4827         assembly = moduleb->dynamic_image;
4828         domain = mono_object_domain (assemblyb);
4829
4830         if (assembly->text_rva)
4831                 return;
4832
4833         assembly->text_rva = START_TEXT_RVA;
4834
4835         if (moduleb->is_main) {
4836                 mono_image_emit_manifest (moduleb);
4837         }
4838
4839         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840         table->rows = 1; /* .<Module> */
4841         table->next_idx++;
4842         alloc_table (table, table->rows);
4843         /*
4844          * Set the first entry.
4845          */
4846         values = table->values + table->columns;
4847         values [MONO_TYPEDEF_FLAGS] = 0;
4848         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4849         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4850         values [MONO_TYPEDEF_EXTENDS] = 0;
4851         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4852         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4853
4854         /* 
4855          * handle global methods 
4856          * FIXME: test what to do when global methods are defined in multiple modules.
4857          */
4858         if (moduleb->global_methods) {
4859                 table = &assembly->tables [MONO_TABLE_METHOD];
4860                 table->rows += mono_array_length (moduleb->global_methods);
4861                 alloc_table (table, table->rows);
4862                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4863                         mono_image_get_method_info (
4864                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4865         }
4866         if (moduleb->global_fields) {
4867                 table = &assembly->tables [MONO_TABLE_FIELD];
4868                 table->rows += mono_array_length (moduleb->global_fields);
4869                 alloc_table (table, table->rows);
4870                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4871                         mono_image_get_field_info (
4872                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4873         }
4874
4875         table = &assembly->tables [MONO_TABLE_MODULE];
4876         alloc_table (table, 1);
4877         mono_image_fill_module_table (domain, moduleb, assembly);
4878
4879         /* Collect all types into a list sorted by their table_idx */
4880         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4881
4882         if (moduleb->types)
4883                 for (i = 0; i < moduleb->num_types; ++i) {
4884                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4885                         collect_types (&types, type);
4886                 }
4887
4888         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4889         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4890         table->rows += mono_ptr_array_size (types);
4891         alloc_table (table, table->rows);
4892
4893         /*
4894          * Emit type names + namespaces at one place inside the string heap,
4895          * so load_class_names () needs to touch fewer pages.
4896          */
4897         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4898                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4899                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4900         }
4901         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4902                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4903                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4904         }
4905
4906         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4907                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4908                 mono_image_get_type_info (domain, type, assembly);
4909         }
4910
4911         /* 
4912          * table->rows is already set above and in mono_image_fill_module_table.
4913          */
4914         /* add all the custom attributes at the end, once all the indexes are stable */
4915         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4916
4917         /* CAS assembly permissions */
4918         if (assemblyb->permissions_minimum)
4919                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4920         if (assemblyb->permissions_optional)
4921                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4922         if (assemblyb->permissions_refused)
4923                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4924
4925         module_add_cattrs (assembly, moduleb);
4926
4927         /* fixup tokens */
4928         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4929
4930         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4931          * the final tokens and don't need another fixup pass. */
4932
4933         if (moduleb->global_methods) {
4934                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4935                         MonoReflectionMethodBuilder *mb = mono_array_get (
4936                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4937                         mono_image_add_methodimpl (assembly, mb);
4938                 }
4939         }
4940
4941         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4942                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4943                 if (type->methods) {
4944                         for (j = 0; j < type->num_methods; ++j) {
4945                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4946                                         type->methods, MonoReflectionMethodBuilder*, j);
4947
4948                                 mono_image_add_methodimpl (assembly, mb);
4949                         }
4950                 }
4951         }
4952
4953         mono_ptr_array_destroy (types);
4954
4955         fixup_cattrs (assembly);
4956 }
4957
4958 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4959
4960 void
4961 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4962 {
4963         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4964 }
4965
4966 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4967
4968
4969 typedef struct {
4970         guint32 import_lookup_table;
4971         guint32 timestamp;
4972         guint32 forwarder;
4973         guint32 name_rva;
4974         guint32 import_address_table_rva;
4975 } MonoIDT;
4976
4977 typedef struct {
4978         guint32 name_rva;
4979         guint32 flags;
4980 } MonoILT;
4981
4982 #ifndef DISABLE_REFLECTION_EMIT
4983
4984 /*
4985  * mono_image_insert_string:
4986  * @module: module builder object
4987  * @str: a string
4988  *
4989  * Insert @str into the user string stream of @module.
4990  */
4991 guint32
4992 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4993 {
4994         MonoDynamicImage *assembly;
4995         guint32 idx;
4996         char buf [16];
4997         char *b = buf;
4998         
4999         if (!module->dynamic_image)
5000                 mono_image_module_basic_init (module);
5001
5002         assembly = module->dynamic_image;
5003         
5004         if (assembly->save) {
5005                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5006                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5007 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5008         {
5009                 char *swapped = g_malloc (2 * mono_string_length (str));
5010                 const char *p = (const char*)mono_string_chars (str);
5011
5012                 swap_with_size (swapped, p, 2, mono_string_length (str));
5013                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5014                 g_free (swapped);
5015         }
5016 #else
5017                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5018 #endif
5019                 mono_image_add_stream_data (&assembly->us, "", 1);
5020         } else {
5021                 idx = assembly->us.index ++;
5022         }
5023
5024         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5025
5026         return MONO_TOKEN_STRING | idx;
5027 }
5028
5029 guint32
5030 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5031 {
5032         MonoClass *klass;
5033         guint32 token = 0;
5034         MonoMethodSignature *sig;
5035
5036         klass = obj->vtable->klass;
5037         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5038                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5039                 MonoMethodSignature *old;
5040                 guint32 sig_token, parent;
5041                 int nargs, i;
5042
5043                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5044
5045                 nargs = mono_array_length (opt_param_types);
5046                 old = mono_method_signature (method);
5047                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5048
5049                 sig->hasthis = old->hasthis;
5050                 sig->explicit_this = old->explicit_this;
5051                 sig->call_convention = old->call_convention;
5052                 sig->generic_param_count = old->generic_param_count;
5053                 sig->param_count = old->param_count + nargs;
5054                 sig->sentinelpos = old->param_count;
5055                 sig->ret = old->ret;
5056
5057                 for (i = 0; i < old->param_count; i++)
5058                         sig->params [i] = old->params [i];
5059
5060                 for (i = 0; i < nargs; i++) {
5061                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5062                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5063                 }
5064
5065                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5066                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5067                 parent >>= MONO_TYPEDEFORREF_BITS;
5068
5069                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5070                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5071
5072                 sig_token = method_encode_signature (assembly, sig);
5073                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5074         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5075                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5076                 ReflectionMethodBuilder rmb;
5077                 guint32 parent, sig_token;
5078                 int nopt_args, nparams, ngparams, i;
5079                 char *name;
5080
5081                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5082                 rmb.opt_types = opt_param_types;
5083                 nopt_args = mono_array_length (opt_param_types);
5084
5085                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5086                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5087                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5088
5089                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5090                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5091                 sig->call_convention = rmb.call_conv;
5092                 sig->generic_param_count = ngparams;
5093                 sig->param_count = nparams + nopt_args;
5094                 sig->sentinelpos = nparams;
5095                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5096
5097                 for (i = 0; i < nparams; i++) {
5098                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5099                         sig->params [i] = mono_reflection_type_get_handle (rt);
5100                 }
5101
5102                 for (i = 0; i < nopt_args; i++) {
5103                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5104                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5105                 }
5106
5107                 sig_token = method_builder_encode_signature (assembly, &rmb);
5108
5109                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5110                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5111
5112                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5113                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5114
5115                 name = mono_string_to_utf8 (rmb.name);
5116                 token = mono_image_get_varargs_method_token (
5117                         assembly, parent, name, sig_token);
5118                 g_free (name);
5119         } else {
5120                 g_error ("requested method token for %s\n", klass->name);
5121         }
5122
5123         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5124         register_dyn_token (assembly, token, obj);
5125         return token;
5126 }
5127
5128 /*
5129  * mono_image_create_token:
5130  * @assembly: a dynamic assembly
5131  * @obj:
5132  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5133  *
5134  * Get a token to insert in the IL code stream for the given MemberInfo.
5135  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5136  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5137  * entry.
5138  */
5139 guint32
5140 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5141                                                  gboolean create_open_instance, gboolean register_token)
5142 {
5143         MonoClass *klass;
5144         guint32 token = 0;
5145
5146         klass = obj->vtable->klass;
5147
5148         /* Check for user defined reflection objects */
5149         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5150         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5151                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5152
5153         if (strcmp (klass->name, "MethodBuilder") == 0) {
5154                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5155                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5156
5157                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5158                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5159                 else
5160                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5161                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5162         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5163                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5164                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5165
5166                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5167                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5168                 else
5169                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5170                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5171         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5172                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5173                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5174                 if (tb->generic_params) {
5175                         token = mono_image_get_generic_field_token (assembly, fb);
5176                 } else {
5177                         if (tb->module->dynamic_image == assembly) {
5178                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5179                         } else {
5180                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5181                         }
5182                 }
5183         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5184                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5185                 if (create_open_instance && tb->generic_params) {
5186                         MonoType *type;
5187                         init_type_builder_generics (obj);
5188                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5190                         token = mono_metadata_token_from_dor (token);
5191                 } else if (tb->module->dynamic_image == assembly) {
5192                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5193                 } else {
5194                         MonoType *type;
5195                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5196                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5197                 }
5198         } else if (strcmp (klass->name, "MonoType") == 0) {
5199                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5200                 MonoClass *mc = mono_class_from_mono_type (type);
5201                 token = mono_metadata_token_from_dor (
5202                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5203         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5204                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5205                 token = mono_metadata_token_from_dor (
5206                         mono_image_typedef_or_ref (assembly, type));
5207         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5208                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5209                 token = mono_metadata_token_from_dor (
5210                         mono_image_typedef_or_ref (assembly, type));
5211         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5212                    strcmp (klass->name, "MonoMethod") == 0 ||
5213                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5214                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5215                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5216                 if (m->method->is_inflated) {
5217                         if (create_open_instance)
5218                                 token = mono_image_get_methodspec_token (assembly, m->method);
5219                         else
5220                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5221                 } else if ((m->method->klass->image == &assembly->image) &&
5222                          !m->method->klass->generic_class) {
5223                         static guint32 method_table_idx = 0xffffff;
5224                         if (m->method->klass->wastypebuilder) {
5225                                 /* we use the same token as the one that was assigned
5226                                  * to the Methodbuilder.
5227                                  * FIXME: do the equivalent for Fields.
5228                                  */
5229                                 token = m->method->token;
5230                         } else {
5231                                 /*
5232                                  * Each token should have a unique index, but the indexes are
5233                                  * assigned by managed code, so we don't know about them. An
5234                                  * easy solution is to count backwards...
5235                                  */
5236                                 method_table_idx --;
5237                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5238                         }
5239                 } else {
5240                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5241                 }
5242                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5243         } else if (strcmp (klass->name, "MonoField") == 0) {
5244                 MonoReflectionField *f = (MonoReflectionField *)obj;
5245                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5246                         static guint32 field_table_idx = 0xffffff;
5247                         field_table_idx --;
5248                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5249                 } else {
5250                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5251                 }
5252                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5253         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5254                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5255                 token = mono_image_get_array_token (assembly, m);
5256         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5257                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5258                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5259         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5260                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5261                 token = mono_metadata_token_from_dor (
5262                         mono_image_typedef_or_ref (assembly, type));
5263         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5264                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5265                 token = mono_image_get_field_on_inst_token (assembly, f);
5266         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5267                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5268                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5269         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5270                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5271                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5272         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5273                 MonoReflectionType *type = (MonoReflectionType *)obj;
5274                 token = mono_metadata_token_from_dor (
5275                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5276         } else {
5277                 g_error ("requested token for %s\n", klass->name);
5278         }
5279
5280         if (register_token)
5281                 mono_image_register_token (assembly, token, obj);
5282
5283         return token;
5284 }
5285
5286 /*
5287  * mono_image_register_token:
5288  *
5289  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5290  * the Module.ResolveXXXToken () methods to work.
5291  */
5292 void
5293 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5294 {
5295         MonoObject *prev;
5296
5297         dynamic_image_lock (assembly);
5298         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5299         if (prev) {
5300                 /* There could be multiple MethodInfo objects with the same token */
5301                 //g_assert (prev == obj);
5302         } else {
5303                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5304         }
5305         dynamic_image_unlock (assembly);
5306 }
5307
5308 static MonoDynamicImage*
5309 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5310 {
5311         static const guchar entrycode [16] = {0xff, 0x25, 0};
5312         MonoDynamicImage *image;
5313         int i;
5314
5315         const char *version;
5316
5317         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5318                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5319         else
5320                 version = mono_get_runtime_info ()->runtime_version;
5321
5322 #if HAVE_BOEHM_GC
5323         /* The MonoGHashTable's need GC tracking */
5324         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5325 #else
5326         image = g_new0 (MonoDynamicImage, 1);
5327 #endif
5328
5329         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5330         
5331         /*g_print ("created image %p\n", image);*/
5332         /* keep in sync with image.c */
5333         image->image.name = assembly_name;
5334         image->image.assembly_name = image->image.name; /* they may be different */
5335         image->image.module_name = module_name;
5336         image->image.version = g_strdup (version);
5337         image->image.md_version_major = 1;
5338         image->image.md_version_minor = 1;
5339         image->image.dynamic = TRUE;
5340
5341         image->image.references = g_new0 (MonoAssembly*, 1);
5342         image->image.references [0] = NULL;
5343
5344         mono_image_init (&image->image);
5345
5346         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5347         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5348         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5349         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5350         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5351         image->handleref = g_hash_table_new (NULL, NULL);
5352         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5353         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5354         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5355         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5356         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5357         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5358         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5359         image->gen_params = g_ptr_array_new ();
5360         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5361
5362         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5363         string_heap_init (&image->sheap);
5364         mono_image_add_stream_data (&image->us, "", 1);
5365         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5366         /* import tables... */
5367         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5368         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5369         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5370         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5371         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5372         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5373         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5374         stream_data_align (&image->code);
5375
5376         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5377
5378         for (i=0; i < MONO_TABLE_NUM; ++i) {
5379                 image->tables [i].next_idx = 1;
5380                 image->tables [i].columns = table_sizes [i];
5381         }
5382
5383         image->image.assembly = (MonoAssembly*)assembly;
5384         image->run = assembly->run;
5385         image->save = assembly->save;
5386         image->pe_kind = 0x1; /* ILOnly */
5387         image->machine = 0x14c; /* I386 */
5388         
5389         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5390
5391         dynamic_images_lock ();
5392
5393         if (!dynamic_images)
5394                 dynamic_images = g_ptr_array_new ();
5395
5396         g_ptr_array_add (dynamic_images, image);
5397
5398         dynamic_images_unlock ();
5399
5400         return image;
5401 }
5402 #endif
5403
5404 static void
5405 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5406 {
5407         g_free (key);
5408 }
5409
5410 static void
5411 release_hashtable (MonoGHashTable **hash)
5412 {
5413         if (*hash) {
5414                 mono_g_hash_table_destroy (*hash);
5415                 *hash = NULL;
5416         }
5417 }
5418
5419 void
5420 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5421 {
5422         release_hashtable (&image->token_fixups);
5423         release_hashtable (&image->handleref_managed);
5424         release_hashtable (&image->tokens);
5425         release_hashtable (&image->remapped_tokens);
5426         release_hashtable (&image->generic_def_objects);
5427         release_hashtable (&image->methodspec);
5428 }
5429
5430 // Free dynamic image pass one: Free resources but not image itself
5431 void
5432 mono_dynamic_image_free (MonoDynamicImage *image)
5433 {
5434         MonoDynamicImage *di = image;
5435         GList *list;
5436         int i;
5437
5438         if (di->methodspec)
5439                 mono_g_hash_table_destroy (di->methodspec);
5440         if (di->typespec)
5441                 g_hash_table_destroy (di->typespec);
5442         if (di->typeref)
5443                 g_hash_table_destroy (di->typeref);
5444         if (di->handleref)
5445                 g_hash_table_destroy (di->handleref);
5446         if (di->handleref_managed)
5447                 mono_g_hash_table_destroy (di->handleref_managed);
5448         if (di->tokens)
5449                 mono_g_hash_table_destroy (di->tokens);
5450         if (di->remapped_tokens)
5451                 mono_g_hash_table_destroy (di->remapped_tokens);
5452         if (di->generic_def_objects)
5453                 mono_g_hash_table_destroy (di->generic_def_objects);
5454         if (di->blob_cache) {
5455                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5456                 g_hash_table_destroy (di->blob_cache);
5457         }
5458         if (di->standalonesig_cache)
5459                 g_hash_table_destroy (di->standalonesig_cache);
5460         for (list = di->array_methods; list; list = list->next) {
5461                 ArrayMethod *am = (ArrayMethod *)list->data;
5462                 g_free (am->sig);
5463                 g_free (am->name);
5464                 g_free (am);
5465         }
5466         g_list_free (di->array_methods);
5467         if (di->gen_params) {
5468                 for (i = 0; i < di->gen_params->len; i++) {
5469                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5470                         mono_gc_deregister_root ((char*) &entry->gparam);
5471                         g_free (entry);
5472                 }
5473                 g_ptr_array_free (di->gen_params, TRUE);
5474         }
5475         if (di->token_fixups)
5476                 mono_g_hash_table_destroy (di->token_fixups);
5477         if (di->method_to_table_idx)
5478                 g_hash_table_destroy (di->method_to_table_idx);
5479         if (di->field_to_table_idx)
5480                 g_hash_table_destroy (di->field_to_table_idx);
5481         if (di->method_aux_hash)
5482                 g_hash_table_destroy (di->method_aux_hash);
5483         if (di->vararg_aux_hash)
5484                 g_hash_table_destroy (di->vararg_aux_hash);
5485         g_free (di->strong_name);
5486         g_free (di->win32_res);
5487         if (di->public_key)
5488                 g_free (di->public_key);
5489
5490         /*g_print ("string heap destroy for image %p\n", di);*/
5491         mono_dynamic_stream_reset (&di->sheap);
5492         mono_dynamic_stream_reset (&di->code);
5493         mono_dynamic_stream_reset (&di->resources);
5494         mono_dynamic_stream_reset (&di->us);
5495         mono_dynamic_stream_reset (&di->blob);
5496         mono_dynamic_stream_reset (&di->tstream);
5497         mono_dynamic_stream_reset (&di->guid);
5498         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5499                 g_free (di->tables [i].values);
5500         }
5501
5502         dynamic_images_lock ();
5503
5504         if (dynamic_images)
5505                 g_ptr_array_remove (dynamic_images, di);
5506
5507         dynamic_images_unlock ();
5508 }
5509
5510 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5511 void
5512 mono_dynamic_image_free_image (MonoDynamicImage *image)
5513 {
5514         /* See create_dynamic_mono_image () */
5515 #if HAVE_BOEHM_GC
5516         /* Allocated using GC_MALLOC */
5517 #else
5518         g_free (image);
5519 #endif
5520 }
5521
5522 #ifndef DISABLE_REFLECTION_EMIT
5523
5524 /*
5525  * mono_image_basic_init:
5526  * @assembly: an assembly builder object
5527  *
5528  * Create the MonoImage that represents the assembly builder and setup some
5529  * of the helper hash table and the basic metadata streams.
5530  */
5531 void
5532 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5533 {
5534         MonoDynamicAssembly *assembly;
5535         MonoDynamicImage *image;
5536         MonoDomain *domain = mono_object_domain (assemblyb);
5537         
5538         if (assemblyb->dynamic_assembly)
5539                 return;
5540
5541 #if HAVE_BOEHM_GC
5542         /* assembly->assembly.image might be GC allocated */
5543         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5544 #else
5545         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5546 #endif
5547
5548         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5549         
5550         assembly->assembly.ref_count = 1;
5551         assembly->assembly.dynamic = TRUE;
5552         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5553         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5554         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5555         if (assemblyb->culture)
5556                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5557         else
5558                 assembly->assembly.aname.culture = g_strdup ("");
5559
5560         if (assemblyb->version) {
5561                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5562                         char **version = g_strsplit (vstr, ".", 4);
5563                         char **parts = version;
5564                         assembly->assembly.aname.major = atoi (*parts++);
5565                         assembly->assembly.aname.minor = atoi (*parts++);
5566                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5567                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5568
5569                         g_strfreev (version);
5570                         g_free (vstr);
5571         } else {
5572                         assembly->assembly.aname.major = 0;
5573                         assembly->assembly.aname.minor = 0;
5574                         assembly->assembly.aname.build = 0;
5575                         assembly->assembly.aname.revision = 0;
5576         }
5577
5578         assembly->run = assemblyb->access != 2;
5579         assembly->save = assemblyb->access != 1;
5580         assembly->domain = domain;
5581
5582         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5583         image->initial_image = TRUE;
5584         assembly->assembly.aname.name = image->image.name;
5585         assembly->assembly.image = &image->image;
5586         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5587                 /* -1 to correct for the trailing NULL byte */
5588                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5589                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5590                 }
5591                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5592         }
5593
5594         mono_domain_assemblies_lock (domain);
5595         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5596         mono_domain_assemblies_unlock (domain);
5597
5598         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5599         
5600         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5601         
5602         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5603 }
5604
5605 #endif /* !DISABLE_REFLECTION_EMIT */
5606
5607 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5608
5609 static int
5610 calc_section_size (MonoDynamicImage *assembly)
5611 {
5612         int nsections = 0;
5613
5614         /* alignment constraints */
5615         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5616         g_assert ((assembly->code.index % 4) == 0);
5617         assembly->meta_size += 3;
5618         assembly->meta_size &= ~3;
5619         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5620         g_assert ((assembly->resources.index % 4) == 0);
5621
5622         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5623         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5624         nsections++;
5625
5626         if (assembly->win32_res) {
5627                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5628
5629                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5630                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5631                 nsections++;
5632         }
5633
5634         assembly->sections [MONO_SECTION_RELOC].size = 12;
5635         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5636         nsections++;
5637
5638         return nsections;
5639 }
5640
5641 typedef struct {
5642         guint32 id;
5643         guint32 offset;
5644         GSList *children;
5645         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5646 } ResTreeNode;
5647
5648 static int
5649 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5650 {
5651         ResTreeNode *t1 = (ResTreeNode*)a;
5652         ResTreeNode *t2 = (ResTreeNode*)b;
5653
5654         return t1->id - t2->id;
5655 }
5656
5657 /*
5658  * resource_tree_create:
5659  *
5660  *  Organize the resources into a resource tree.
5661  */
5662 static ResTreeNode *
5663 resource_tree_create (MonoArray *win32_resources)
5664 {
5665         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5666         GSList *l;
5667         int i;
5668
5669         tree = g_new0 (ResTreeNode, 1);
5670         
5671         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5672                 MonoReflectionWin32Resource *win32_res =
5673                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5674
5675                 /* Create node */
5676
5677                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5678                 lang_node = g_new0 (ResTreeNode, 1);
5679                 lang_node->id = win32_res->lang_id;
5680                 lang_node->win32_res = win32_res;
5681
5682                 /* Create type node if neccesary */
5683                 type_node = NULL;
5684                 for (l = tree->children; l; l = l->next)
5685                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5686                                 type_node = (ResTreeNode*)l->data;
5687                                 break;
5688                         }
5689
5690                 if (!type_node) {
5691                         type_node = g_new0 (ResTreeNode, 1);
5692                         type_node->id = win32_res->res_type;
5693
5694                         /* 
5695                          * The resource types have to be sorted otherwise
5696                          * Windows Explorer can't display the version information.
5697                          */
5698                         tree->children = g_slist_insert_sorted (tree->children, 
5699                                 type_node, resource_tree_compare_by_id);
5700                 }
5701
5702                 /* Create res node if neccesary */
5703                 res_node = NULL;
5704                 for (l = type_node->children; l; l = l->next)
5705                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5706                                 res_node = (ResTreeNode*)l->data;
5707                                 break;
5708                         }
5709
5710                 if (!res_node) {
5711                         res_node = g_new0 (ResTreeNode, 1);
5712                         res_node->id = win32_res->res_id;
5713                         type_node->children = g_slist_append (type_node->children, res_node);
5714                 }
5715
5716                 res_node->children = g_slist_append (res_node->children, lang_node);
5717         }
5718
5719         return tree;
5720 }
5721
5722 /*
5723  * resource_tree_encode:
5724  * 
5725  *   Encode the resource tree into the format used in the PE file.
5726  */
5727 static void
5728 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5729 {
5730         char *entries;
5731         MonoPEResourceDir dir;
5732         MonoPEResourceDirEntry dir_entry;
5733         MonoPEResourceDataEntry data_entry;
5734         GSList *l;
5735         guint32 res_id_entries;
5736
5737         /*
5738          * For the format of the resource directory, see the article
5739          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5740          * Matt Pietrek
5741          */
5742
5743         memset (&dir, 0, sizeof (dir));
5744         memset (&dir_entry, 0, sizeof (dir_entry));
5745         memset (&data_entry, 0, sizeof (data_entry));
5746
5747         g_assert (sizeof (dir) == 16);
5748         g_assert (sizeof (dir_entry) == 8);
5749         g_assert (sizeof (data_entry) == 16);
5750
5751         node->offset = p - begin;
5752
5753         /* IMAGE_RESOURCE_DIRECTORY */
5754         res_id_entries = g_slist_length (node->children);
5755         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5756
5757         memcpy (p, &dir, sizeof (dir));
5758         p += sizeof (dir);
5759
5760         /* Reserve space for entries */
5761         entries = p;
5762         p += sizeof (dir_entry) * res_id_entries;
5763
5764         /* Write children */
5765         for (l = node->children; l; l = l->next) {
5766                 ResTreeNode *child = (ResTreeNode*)l->data;
5767
5768                 if (child->win32_res) {
5769                         guint32 size;
5770
5771                         child->offset = p - begin;
5772
5773                         /* IMAGE_RESOURCE_DATA_ENTRY */
5774                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5775                         size = mono_array_length (child->win32_res->res_data);
5776                         data_entry.rde_size = GUINT32_TO_LE (size);
5777
5778                         memcpy (p, &data_entry, sizeof (data_entry));
5779                         p += sizeof (data_entry);
5780
5781                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5782                         p += size;
5783                 } else {
5784                         resource_tree_encode (child, begin, p, &p);
5785                 }
5786         }
5787
5788         /* IMAGE_RESOURCE_ENTRY */
5789         for (l = node->children; l; l = l->next) {
5790                 ResTreeNode *child = (ResTreeNode*)l->data;
5791
5792                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5793                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5794
5795                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5796                 entries += sizeof (dir_entry);
5797         }
5798
5799         *endbuf = p;
5800 }
5801
5802 static void
5803 resource_tree_free (ResTreeNode * node)
5804 {
5805         GSList * list;
5806         for (list = node->children; list; list = list->next)
5807                 resource_tree_free ((ResTreeNode*)list->data);
5808         g_slist_free(node->children);
5809         g_free (node);
5810 }
5811
5812 static void
5813 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5814 {
5815         char *buf;
5816         char *p;
5817         guint32 size, i;
5818         MonoReflectionWin32Resource *win32_res;
5819         ResTreeNode *tree;
5820
5821         if (!assemblyb->win32_resources)
5822                 return;
5823
5824         /*
5825          * Resources are stored in a three level tree inside the PE file.
5826          * - level one contains a node for each type of resource
5827          * - level two contains a node for each resource
5828          * - level three contains a node for each instance of a resource for a
5829          *   specific language.
5830          */
5831
5832         tree = resource_tree_create (assemblyb->win32_resources);
5833
5834         /* Estimate the size of the encoded tree */
5835         size = 0;
5836         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5837                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5838                 size += mono_array_length (win32_res->res_data);
5839         }
5840         /* Directory structure */
5841         size += mono_array_length (assemblyb->win32_resources) * 256;
5842         p = buf = (char *)g_malloc (size);
5843
5844         resource_tree_encode (tree, p, p, &p);
5845
5846         g_assert (p - buf <= size);
5847
5848         assembly->win32_res = (char *)g_malloc (p - buf);
5849         assembly->win32_res_size = p - buf;
5850         memcpy (assembly->win32_res, buf, p - buf);
5851
5852         g_free (buf);
5853         resource_tree_free (tree);
5854 }
5855
5856 static void
5857 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5858 {
5859         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5860         int i;
5861
5862         p += sizeof (MonoPEResourceDir);
5863         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5864                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5865                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5866                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5867                         fixup_resource_directory (res_section, child, rva);
5868                 } else {
5869                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5870                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5871                 }
5872
5873                 p += sizeof (MonoPEResourceDirEntry);
5874         }
5875 }
5876
5877 static void
5878 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5879 {
5880         guint32 dummy;
5881         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5882                 g_error ("WriteFile returned %d\n", GetLastError ());
5883 }
5884
5885 /*
5886  * mono_image_create_pefile:
5887  * @mb: a module builder object
5888  * 
5889  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5890  * assembly->pefile where it can be easily retrieved later in chunks.
5891  */
5892 void
5893 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5894 {
5895         MonoMSDOSHeader *msdos;
5896         MonoDotNetHeader *header;
5897         MonoSectionTable *section;
5898         MonoCLIHeader *cli_header;
5899         guint32 size, image_size, virtual_base, text_offset;
5900         guint32 header_start, section_start, file_offset, virtual_offset;
5901         MonoDynamicImage *assembly;
5902         MonoReflectionAssemblyBuilder *assemblyb;
5903         MonoDynamicStream pefile_stream = {0};
5904         MonoDynamicStream *pefile = &pefile_stream;
5905         int i, nsections;
5906         guint32 *rva, value;
5907         guchar *p;
5908         static const unsigned char msheader[] = {
5909                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5910                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5911                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5912                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5913                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5914                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5915                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5916                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5917         };
5918
5919         assemblyb = mb->assemblyb;
5920
5921         mono_image_basic_init (assemblyb);
5922         assembly = mb->dynamic_image;
5923
5924         assembly->pe_kind = assemblyb->pe_kind;
5925         assembly->machine = assemblyb->machine;
5926         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5927         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5928         
5929         mono_image_build_metadata (mb);
5930
5931         if (mb->is_main && assemblyb->resources) {
5932                 int len = mono_array_length (assemblyb->resources);
5933                 for (i = 0; i < len; ++i)
5934                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5935         }
5936
5937         if (mb->resources) {
5938                 int len = mono_array_length (mb->resources);
5939                 for (i = 0; i < len; ++i)
5940                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5941         }
5942
5943         build_compressed_metadata (assembly);
5944
5945         if (mb->is_main)
5946                 assembly_add_win32_resources (assembly, assemblyb);
5947
5948         nsections = calc_section_size (assembly);
5949         
5950         /* The DOS header and stub */
5951         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5952         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5953
5954         /* the dotnet header */
5955         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5956
5957         /* the section tables */
5958         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5959
5960         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5961         virtual_offset = VIRT_ALIGN;
5962         image_size = 0;
5963
5964         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5965                 if (!assembly->sections [i].size)
5966                         continue;
5967                 /* align offsets */
5968                 file_offset += FILE_ALIGN - 1;
5969                 file_offset &= ~(FILE_ALIGN - 1);
5970                 virtual_offset += VIRT_ALIGN - 1;
5971                 virtual_offset &= ~(VIRT_ALIGN - 1);
5972
5973                 assembly->sections [i].offset = file_offset;
5974                 assembly->sections [i].rva = virtual_offset;
5975
5976                 file_offset += assembly->sections [i].size;
5977                 virtual_offset += assembly->sections [i].size;
5978                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5979         }
5980
5981         file_offset += FILE_ALIGN - 1;
5982         file_offset &= ~(FILE_ALIGN - 1);
5983
5984         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5985
5986         /* back-patch info */
5987         msdos = (MonoMSDOSHeader*)pefile->data;
5988         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5989
5990         header = (MonoDotNetHeader*)(pefile->data + header_start);
5991         header->pesig [0] = 'P';
5992         header->pesig [1] = 'E';
5993         
5994         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5995         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5996         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5997         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5998         if (assemblyb->pekind == 1) {
5999                 /* it's a dll */
6000                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6001         } else {
6002                 /* it's an exe */
6003                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6004         }
6005
6006         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6007
6008         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6009         header->pe.pe_major = 6;
6010         header->pe.pe_minor = 0;
6011         size = assembly->sections [MONO_SECTION_TEXT].size;
6012         size += FILE_ALIGN - 1;
6013         size &= ~(FILE_ALIGN - 1);
6014         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6015         size = assembly->sections [MONO_SECTION_RSRC].size;
6016         size += FILE_ALIGN - 1;
6017         size &= ~(FILE_ALIGN - 1);
6018         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6019         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6020         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6021         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6022         /* pe_rva_entry_point always at the beginning of the text section */
6023         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6024
6025         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6026         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6027         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6028         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6029         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6030         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6031         size = section_start;
6032         size += FILE_ALIGN - 1;
6033         size &= ~(FILE_ALIGN - 1);
6034         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6035         size = image_size;
6036         size += VIRT_ALIGN - 1;
6037         size &= ~(VIRT_ALIGN - 1);
6038         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6039
6040         /*
6041         // Translate the PEFileKind value to the value expected by the Windows loader
6042         */
6043         {
6044                 short kind;
6045
6046                 /*
6047                 // PEFileKinds.Dll == 1
6048                 // PEFileKinds.ConsoleApplication == 2
6049                 // PEFileKinds.WindowApplication == 3
6050                 //
6051                 // need to get:
6052                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6053                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6054                 */
6055                 if (assemblyb->pekind == 3)
6056                         kind = 2;
6057                 else
6058                         kind = 3;
6059                 
6060                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6061         }    
6062         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6063         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6064         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6065         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6066         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6067         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6068
6069         /* fill data directory entries */
6070
6071         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6072         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6073
6074         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6075         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6076
6077         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6078         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6079         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6080         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6081         /* patch entrypoint name */
6082         if (assemblyb->pekind == 1)
6083                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6084         else
6085                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6086         /* patch imported function RVA name */
6087         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6088         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6089
6090         /* the import table */
6091         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6092         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6093         /* patch imported dll RVA name and other entries in the dir */
6094         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6095         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6096         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6097         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6098         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6099         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6100
6101         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6102         value = (assembly->text_rva + assembly->imp_names_offset);
6103         *p++ = (value) & 0xff;
6104         *p++ = (value >> 8) & (0xff);
6105         *p++ = (value >> 16) & (0xff);
6106         *p++ = (value >> 24) & (0xff);
6107
6108         /* the CLI header info */
6109         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6110         cli_header->ch_size = GUINT32_FROM_LE (72);
6111         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6112         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6113         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6114         if (assemblyb->entry_point) {
6115                 guint32 table_idx = 0;
6116                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6117                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6118                         table_idx = methodb->table_idx;
6119                 } else {
6120                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6121                 }
6122                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6123         } else {
6124                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6125         }
6126         /* The embedded managed resources */
6127         text_offset = assembly->text_rva + assembly->code.index;
6128         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6129         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6130         text_offset += assembly->resources.index;
6131         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6132         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6133         text_offset += assembly->meta_size;
6134         if (assembly->strong_name_size) {
6135                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6136                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6137                 text_offset += assembly->strong_name_size;
6138         }
6139
6140         /* write the section tables and section content */
6141         section = (MonoSectionTable*)(pefile->data + section_start);
6142         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6143                 static const char section_names [][7] = {
6144                         ".text", ".rsrc", ".reloc"
6145                 };
6146                 if (!assembly->sections [i].size)
6147                         continue;
6148                 strcpy (section->st_name, section_names [i]);
6149                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6150                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6151                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6152                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6153                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6154                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6155                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6156                 section ++;
6157         }
6158         
6159         checked_write_file (file, pefile->data, pefile->index);
6160         
6161         mono_dynamic_stream_reset (pefile);
6162         
6163         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6164                 if (!assembly->sections [i].size)
6165                         continue;
6166                 
6167                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6168                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6169                 
6170                 switch (i) {
6171                 case MONO_SECTION_TEXT:
6172                         /* patch entry point */
6173                         p = (guchar*)(assembly->code.data + 2);
6174                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6175                         *p++ = (value) & 0xff;
6176                         *p++ = (value >> 8) & 0xff;
6177                         *p++ = (value >> 16) & 0xff;
6178                         *p++ = (value >> 24) & 0xff;
6179                 
6180                         checked_write_file (file, assembly->code.data, assembly->code.index);
6181                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6182                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6183                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6184                                 
6185
6186                         g_free (assembly->image.raw_metadata);
6187                         break;
6188                 case MONO_SECTION_RELOC: {
6189                         struct {
6190                                 guint32 page_rva;
6191                                 guint32 block_size;
6192                                 guint16 type_and_offset;
6193                                 guint16 term;
6194                         } reloc;
6195                         
6196                         g_assert (sizeof (reloc) == 12);
6197                         
6198                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6199                         reloc.block_size = GUINT32_FROM_LE (12);
6200                         
6201                         /* 
6202                          * the entrypoint is always at the start of the text section 
6203                          * 3 is IMAGE_REL_BASED_HIGHLOW
6204                          * 2 is patch_size_rva - text_rva
6205                          */
6206                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6207                         reloc.term = 0;
6208                         
6209                         checked_write_file (file, &reloc, sizeof (reloc));
6210                         
6211                         break;
6212                 }
6213                 case MONO_SECTION_RSRC:
6214                         if (assembly->win32_res) {
6215
6216                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6217                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6218                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6219                         }
6220                         break;
6221                 default:
6222                         g_assert_not_reached ();
6223                 }
6224         }
6225         
6226         /* check that the file is properly padded */
6227         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6228                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6229         if (! SetEndOfFile (file))
6230                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6231         
6232         mono_dynamic_stream_reset (&assembly->code);
6233         mono_dynamic_stream_reset (&assembly->us);
6234         mono_dynamic_stream_reset (&assembly->blob);
6235         mono_dynamic_stream_reset (&assembly->guid);
6236         mono_dynamic_stream_reset (&assembly->sheap);
6237
6238         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6239         g_hash_table_destroy (assembly->blob_cache);
6240         assembly->blob_cache = NULL;
6241 }
6242
6243 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6244
6245 void
6246 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6247 {
6248         g_assert_not_reached ();
6249 }
6250
6251 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6252
6253 #ifndef DISABLE_REFLECTION_EMIT
6254
6255 MonoReflectionModule *
6256 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6257 {
6258         char *name;
6259         MonoImage *image;
6260         MonoImageOpenStatus status;
6261         MonoDynamicAssembly *assembly;
6262         guint32 module_count;
6263         MonoImage **new_modules;
6264         gboolean *new_modules_loaded;
6265         
6266         name = mono_string_to_utf8 (fileName);
6267
6268         image = mono_image_open (name, &status);
6269         if (!image) {
6270                 MonoException *exc;
6271                 if (status == MONO_IMAGE_ERROR_ERRNO)
6272                         exc = mono_get_exception_file_not_found (fileName);
6273                 else
6274                         exc = mono_get_exception_bad_image_format (name);
6275                 g_free (name);
6276                 mono_raise_exception (exc);
6277         }
6278
6279         g_free (name);
6280
6281         assembly = ab->dynamic_assembly;
6282         image->assembly = (MonoAssembly*)assembly;
6283
6284         module_count = image->assembly->image->module_count;
6285         new_modules = g_new0 (MonoImage *, module_count + 1);
6286         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6287
6288         if (image->assembly->image->modules)
6289                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6290         if (image->assembly->image->modules_loaded)
6291                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6292         new_modules [module_count] = image;
6293         new_modules_loaded [module_count] = TRUE;
6294         mono_image_addref (image);
6295
6296         g_free (image->assembly->image->modules);
6297         image->assembly->image->modules = new_modules;
6298         image->assembly->image->modules_loaded = new_modules_loaded;
6299         image->assembly->image->module_count ++;
6300
6301         mono_assembly_load_references (image, &status);
6302         if (status) {
6303                 mono_image_close (image);
6304                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6305         }
6306
6307         return mono_module_get_object (mono_domain_get (), image);
6308 }
6309
6310 #endif /* DISABLE_REFLECTION_EMIT */
6311
6312 /*
6313  * We need to return always the same object for MethodInfo, FieldInfo etc..
6314  * but we need to consider the reflected type.
6315  * type uses a different hash, since it uses custom hash/equal functions.
6316  */
6317
6318 typedef struct {
6319         gpointer item;
6320         MonoClass *refclass;
6321 } ReflectedEntry;
6322
6323 static gboolean
6324 reflected_equal (gconstpointer a, gconstpointer b) {
6325         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6326         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6327
6328         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6329 }
6330
6331 static guint
6332 reflected_hash (gconstpointer a) {
6333         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6334         return mono_aligned_addr_hash (ea->item);
6335 }
6336
6337 #define CHECK_OBJECT(t,p,k)     \
6338         do {    \
6339                 t _obj; \
6340                 ReflectedEntry e;       \
6341                 e.item = (p);   \
6342                 e.refclass = (k);       \
6343                 mono_domain_lock (domain);      \
6344                 if (!domain->refobject_hash)    \
6345                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6346                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6347                         mono_domain_unlock (domain);    \
6348                         return _obj;    \
6349                 }       \
6350         mono_domain_unlock (domain); \
6351         } while (0)
6352
6353 #ifdef HAVE_BOEHM_GC
6354 /* ReflectedEntry doesn't need to be GC tracked */
6355 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6356 #define FREE_REFENTRY(entry) g_free ((entry))
6357 #define REFENTRY_REQUIRES_CLEANUP
6358 #else
6359 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6360 /* FIXME: */
6361 #define FREE_REFENTRY(entry)
6362 #endif
6363
6364 #define CACHE_OBJECT(t,p,o,k)   \
6365         do {    \
6366                 t _obj; \
6367         ReflectedEntry pe; \
6368         pe.item = (p); \
6369         pe.refclass = (k); \
6370         mono_domain_lock (domain); \
6371                 if (!domain->refobject_hash)    \
6372                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6373         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6374         if (!_obj) { \
6375                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6376                     e->item = (p);      \
6377                     e->refclass = (k);  \
6378                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6379             _obj = o; \
6380         } \
6381                 mono_domain_unlock (domain);    \
6382         return _obj; \
6383         } while (0)
6384
6385 static void
6386 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6387 {
6388         mono_domain_lock (domain);
6389         if (domain->refobject_hash) {
6390         ReflectedEntry pe;
6391                 gpointer orig_pe, orig_value;
6392
6393                 pe.item = o;
6394                 pe.refclass = klass;
6395                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6396                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6397                         FREE_REFENTRY (orig_pe);
6398                 }
6399         }
6400         mono_domain_unlock (domain);
6401 }
6402
6403 #ifdef REFENTRY_REQUIRES_CLEANUP
6404 static void
6405 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6406 {
6407         FREE_REFENTRY (key);
6408 }
6409 #endif
6410
6411 void
6412 mono_reflection_cleanup_domain (MonoDomain *domain)
6413 {
6414         if (domain->refobject_hash) {
6415 /*let's avoid scanning the whole hashtable if not needed*/
6416 #ifdef REFENTRY_REQUIRES_CLEANUP
6417                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6418 #endif
6419                 mono_g_hash_table_destroy (domain->refobject_hash);
6420                 domain->refobject_hash = NULL;
6421         }
6422 }
6423
6424 #ifndef DISABLE_REFLECTION_EMIT
6425 static gpointer
6426 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6427 {
6428         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6429 }
6430
6431 static gpointer
6432 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6433 {
6434         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6435 }
6436
6437 void
6438 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6439 {
6440         MonoDynamicImage *image = moduleb->dynamic_image;
6441         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6442         if (!image) {
6443                 MonoError error;
6444                 int module_count;
6445                 MonoImage **new_modules;
6446                 MonoImage *ass;
6447                 char *name, *fqname;
6448                 /*
6449                  * FIXME: we already created an image in mono_image_basic_init (), but
6450                  * we don't know which module it belongs to, since that is only 
6451                  * determined at assembly save time.
6452                  */
6453                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6454                 name = mono_string_to_utf8 (ab->name);
6455                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6456                 if (!mono_error_ok (&error)) {
6457                         g_free (name);
6458                         mono_error_raise_exception (&error);
6459                 }
6460                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6461
6462                 moduleb->module.image = &image->image;
6463                 moduleb->dynamic_image = image;
6464                 register_module (mono_object_domain (moduleb), moduleb, image);
6465
6466                 /* register the module with the assembly */
6467                 ass = ab->dynamic_assembly->assembly.image;
6468                 module_count = ass->module_count;
6469                 new_modules = g_new0 (MonoImage *, module_count + 1);
6470
6471                 if (ass->modules)
6472                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6473                 new_modules [module_count] = &image->image;
6474                 mono_image_addref (&image->image);
6475
6476                 g_free (ass->modules);
6477                 ass->modules = new_modules;
6478                 ass->module_count ++;
6479         }
6480 }
6481
6482 void
6483 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6484 {
6485         MonoDynamicImage *image = moduleb->dynamic_image;
6486
6487         g_assert (type->type);
6488         image->wrappers_type = mono_class_from_mono_type (type->type);
6489 }
6490
6491 #endif
6492
6493 /*
6494  * mono_assembly_get_object:
6495  * @domain: an app domain
6496  * @assembly: an assembly
6497  *
6498  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6499  */
6500 MonoReflectionAssembly*
6501 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6502 {
6503         static MonoClass *assembly_type;
6504         MonoReflectionAssembly *res;
6505         
6506         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6507         if (!assembly_type) {
6508                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6509                 if (klass == NULL)
6510                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6511                 g_assert (klass);
6512                 assembly_type = klass;
6513         }
6514         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6515         res->assembly = assembly;
6516
6517         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6518 }
6519
6520
6521
6522 MonoReflectionModule*   
6523 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6524 {
6525         static MonoClass *module_type;
6526         MonoReflectionModule *res;
6527         char* basename;
6528         
6529         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6530         if (!module_type) {
6531                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6532                 if (klass == NULL)
6533                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6534                 g_assert (klass);
6535                 module_type = klass;
6536         }
6537         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6538
6539         res->image = image;
6540         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6541
6542         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6543         basename = g_path_get_basename (image->name);
6544         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6545         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6546         
6547         g_free (basename);
6548
6549         if (image->assembly->image == image) {
6550                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6551         } else {
6552                 int i;
6553                 res->token = 0;
6554                 if (image->assembly->image->modules) {
6555                         for (i = 0; i < image->assembly->image->module_count; i++) {
6556                                 if (image->assembly->image->modules [i] == image)
6557                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6558                         }
6559                         g_assert (res->token);
6560                 }
6561         }
6562
6563         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6564 }
6565
6566 MonoReflectionModule*   
6567 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6568 {
6569         static MonoClass *module_type;
6570         MonoReflectionModule *res;
6571         MonoTableInfo *table;
6572         guint32 cols [MONO_FILE_SIZE];
6573         const char *name;
6574         guint32 i, name_idx;
6575         const char *val;
6576         
6577         if (!module_type) {
6578                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6579                 if (klass == NULL)
6580                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6581                 g_assert (klass);
6582                 module_type = klass;
6583         }
6584         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6585
6586         table = &image->tables [MONO_TABLE_FILE];
6587         g_assert (table_index < table->rows);
6588         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6589
6590         res->image = NULL;
6591         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6592         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6593
6594         /* Check whenever the row has a corresponding row in the moduleref table */
6595         table = &image->tables [MONO_TABLE_MODULEREF];
6596         for (i = 0; i < table->rows; ++i) {
6597                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6598                 val = mono_metadata_string_heap (image, name_idx);
6599                 if (strcmp (val, name) == 0)
6600                         res->image = image->modules [i];
6601         }
6602
6603         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6604         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6605         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6606         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6607         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6608
6609         return res;
6610 }
6611
6612 static gboolean
6613 verify_safe_for_managed_space (MonoType *type)
6614 {
6615         switch (type->type) {
6616 #ifdef DEBUG_HARDER
6617         case MONO_TYPE_ARRAY:
6618                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6619         case MONO_TYPE_PTR:
6620                 return verify_safe_for_managed_space (type->data.type);
6621         case MONO_TYPE_SZARRAY:
6622                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6623         case MONO_TYPE_GENERICINST: {
6624                 MonoGenericInst *inst = type->data.generic_class->inst;
6625                 int i;
6626                 if (!inst->is_open)
6627                         break;
6628                 for (i = 0; i < inst->type_argc; ++i)
6629                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6630                                 return FALSE;
6631                 return TRUE;
6632         }
6633 #endif
6634         case MONO_TYPE_VAR:
6635         case MONO_TYPE_MVAR:
6636                 return TRUE;
6637         default:
6638                 return TRUE;
6639         }
6640 }
6641
6642 static MonoType*
6643 mono_type_normalize (MonoType *type)
6644 {
6645         int i;
6646         MonoGenericClass *gclass;
6647         MonoGenericInst *ginst;
6648         MonoClass *gtd;
6649         MonoGenericContainer *gcontainer;
6650         MonoType **argv = NULL;
6651         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6652
6653         if (type->type != MONO_TYPE_GENERICINST)
6654                 return type;
6655
6656         gclass = type->data.generic_class;
6657         ginst = gclass->context.class_inst;
6658         if (!ginst->is_open)
6659                 return type;
6660
6661         gtd = gclass->container_class;
6662         gcontainer = gtd->generic_container;
6663         argv = g_newa (MonoType*, ginst->type_argc);
6664
6665         for (i = 0; i < ginst->type_argc; ++i) {
6666                 MonoType *t = ginst->type_argv [i], *norm;
6667                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6668                         is_denorm_gtd = FALSE;
6669                 norm = mono_type_normalize (t);
6670                 argv [i] = norm;
6671                 if (norm != t)
6672                         requires_rebind = TRUE;
6673         }
6674
6675         if (is_denorm_gtd)
6676                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6677
6678         if (requires_rebind) {
6679                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6680                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6681         }
6682
6683         return type;
6684 }
6685 /*
6686  * mono_type_get_object:
6687  * @domain: an app domain
6688  * @type: a type
6689  *
6690  * Return an System.MonoType object representing the type @type.
6691  */
6692 MonoReflectionType*
6693 mono_type_get_object (MonoDomain *domain, MonoType *type)
6694 {
6695         MonoError error;
6696         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6697         mono_error_raise_exception (&error);
6698
6699         return ret;
6700 }
6701
6702 MonoReflectionType*
6703 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6704 {
6705         MonoType *norm_type;
6706         MonoReflectionType *res;
6707         MonoClass *klass;
6708
6709         mono_error_init (error);
6710
6711         klass = mono_class_from_mono_type (type);
6712
6713         /*we must avoid using @type as it might have come
6714          * from a mono_metadata_type_dup and the caller
6715          * expects that is can be freed.
6716          * Using the right type from 
6717          */
6718         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6719
6720         /* void is very common */
6721         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6722                 return (MonoReflectionType*)domain->typeof_void;
6723
6724         /*
6725          * If the vtable of the given class was already created, we can use
6726          * the MonoType from there and avoid all locking and hash table lookups.
6727          * 
6728          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6729          * that the resulting object is different.   
6730          */
6731         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6732                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6733                 if (vtable && vtable->type)
6734                         return (MonoReflectionType *)vtable->type;
6735         }
6736
6737         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6738         mono_domain_lock (domain);
6739         if (!domain->type_hash)
6740                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6741                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6742         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6743                 mono_domain_unlock (domain);
6744                 mono_loader_unlock ();
6745                 return res;
6746         }
6747
6748         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6749          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6750          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6751          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6752          * artifact of how generics are encoded and should be transparent to managed code so we
6753          * need to weed out this diference when retrieving managed System.Type objects.
6754          */
6755         norm_type = mono_type_normalize (type);
6756         if (norm_type != type) {
6757                 res = mono_type_get_object_checked (domain, norm_type, error);
6758                 if (!mono_error_ok (error))
6759                         return NULL;
6760                 mono_g_hash_table_insert (domain->type_hash, type, res);
6761                 mono_domain_unlock (domain);
6762                 mono_loader_unlock ();
6763                 return res;
6764         }
6765
6766         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6767         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6768                 g_assert (0);
6769
6770         if (!verify_safe_for_managed_space (type)) {
6771                 mono_domain_unlock (domain);
6772                 mono_loader_unlock ();
6773                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6774         }
6775
6776         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6777                 gboolean is_type_done = TRUE;
6778                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6779                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6780                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6781                 */
6782                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6783                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6784
6785                         if (gparam->owner && gparam->owner->is_method) {
6786                                 MonoMethod *method = gparam->owner->owner.method;
6787                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6788                                         is_type_done = FALSE;
6789                         } else if (gparam->owner && !gparam->owner->is_method) {
6790                                 MonoClass *klass = gparam->owner->owner.klass;
6791                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6792                                         is_type_done = FALSE;
6793                         }
6794                 } 
6795
6796                 /* g_assert_not_reached (); */
6797                 /* should this be considered an error condition? */
6798                 if (is_type_done && !type->byref) {
6799                         mono_domain_unlock (domain);
6800                         mono_loader_unlock ();
6801                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
6802                 }
6803         }
6804         /* This is stored in vtables/JITted code so it has to be pinned */
6805         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
6806         if (!mono_error_ok (error))
6807                 return NULL;
6808
6809         res->type = type;
6810         mono_g_hash_table_insert (domain->type_hash, type, res);
6811
6812         if (type->type == MONO_TYPE_VOID)
6813                 domain->typeof_void = (MonoObject*)res;
6814
6815         mono_domain_unlock (domain);
6816         mono_loader_unlock ();
6817         return res;
6818 }
6819
6820 /*
6821  * mono_method_get_object:
6822  * @domain: an app domain
6823  * @method: a method
6824  * @refclass: the reflected type (can be NULL)
6825  *
6826  * Return an System.Reflection.MonoMethod object representing the method @method.
6827  */
6828 MonoReflectionMethod*
6829 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6830 {
6831         /*
6832          * We use the same C representation for methods and constructors, but the type 
6833          * name in C# is different.
6834          */
6835         static MonoClass *System_Reflection_MonoMethod = NULL;
6836         static MonoClass *System_Reflection_MonoCMethod = NULL;
6837         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6838         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6839         MonoError error;
6840         MonoReflectionType *rt;
6841         MonoClass *klass;
6842         MonoReflectionMethod *ret;
6843
6844         if (method->is_inflated) {
6845                 MonoReflectionGenericMethod *gret;
6846
6847                 if (!refclass)
6848                         refclass = method->klass;
6849                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6850                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6851                         if (!System_Reflection_MonoGenericCMethod)
6852                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6853                         klass = System_Reflection_MonoGenericCMethod;
6854                 } else {
6855                         if (!System_Reflection_MonoGenericMethod)
6856                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6857                         klass = System_Reflection_MonoGenericMethod;
6858                 }
6859                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6860                 gret->method.method = method;
6861
6862                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6863
6864                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6865                 mono_error_raise_exception (&error); /* FIXME don't raise here */
6866
6867                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
6868
6869                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6870         }
6871
6872         if (!refclass)
6873                 refclass = method->klass;
6874
6875         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6876         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6877                 if (!System_Reflection_MonoCMethod)
6878                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6879                 klass = System_Reflection_MonoCMethod;
6880         }
6881         else {
6882                 if (!System_Reflection_MonoMethod)
6883                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6884                 klass = System_Reflection_MonoMethod;
6885         }
6886         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6887         ret->method = method;
6888
6889         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, &error);
6890         mono_error_raise_exception (&error); /* FIXME don't raise here */;
6891
6892         MONO_OBJECT_SETREF (ret, reftype, rt);
6893
6894         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6895 }
6896
6897 /*
6898  * mono_method_clear_object:
6899  *
6900  *   Clear the cached reflection objects for the dynamic method METHOD.
6901  */
6902 void
6903 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6904 {
6905         MonoClass *klass;
6906         g_assert (method_is_dynamic (method));
6907
6908         klass = method->klass;
6909         while (klass) {
6910                 clear_cached_object (domain, method, klass);
6911                 klass = klass->parent;
6912         }
6913         /* Added by mono_param_get_objects () */
6914         clear_cached_object (domain, &(method->signature), NULL);
6915         klass = method->klass;
6916         while (klass) {
6917                 clear_cached_object (domain, &(method->signature), klass);
6918                 klass = klass->parent;
6919         }
6920 }
6921
6922 /*
6923  * mono_field_get_object:
6924  * @domain: an app domain
6925  * @klass: a type
6926  * @field: a field
6927  *
6928  * Return an System.Reflection.MonoField object representing the field @field
6929  * in class @klass.
6930  */
6931 MonoReflectionField*
6932 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6933 {
6934         MonoError error;
6935         MonoReflectionField *result;
6936         result = mono_field_get_object_checked (domain, klass, field, &error);
6937         mono_error_raise_exception (&error);
6938         return result;
6939 }
6940
6941 /*
6942  * mono_field_get_object_checked:
6943  * @domain: an app domain
6944  * @klass: a type
6945  * @field: a field
6946  * @error: set on error
6947  *
6948  * Return an System.Reflection.MonoField object representing the field @field
6949  * in class @klass. On error, returns NULL and sets @error.
6950  */
6951 MonoReflectionField*
6952 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
6953 {
6954         MonoReflectionType *rt;
6955         MonoReflectionField *res;
6956         static MonoClass *monofield_klass;
6957
6958         mono_error_init (error);
6959
6960         CHECK_OBJECT (MonoReflectionField *, field, klass);
6961         if (!monofield_klass)
6962                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6963         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6964         res->klass = klass;
6965         res->field = field;
6966         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6967
6968         if (is_field_on_inst (field)) {
6969                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6970
6971                 rt = mono_type_get_object_checked (domain, field->type, error);
6972                 if (!mono_error_ok (error))
6973                         return NULL;
6974
6975                 MONO_OBJECT_SETREF (res, type, rt);
6976         } else {
6977                 if (field->type) {
6978                         rt = mono_type_get_object_checked (domain, field->type, error);
6979                         if (!mono_error_ok (error))
6980                                 return NULL;
6981
6982                         MONO_OBJECT_SETREF (res, type, rt);
6983                 }
6984                 res->attrs = mono_field_get_flags (field);
6985         }
6986         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6987 }
6988
6989 /*
6990  * mono_property_get_object:
6991  * @domain: an app domain
6992  * @klass: a type
6993  * @property: a property
6994  *
6995  * Return an System.Reflection.MonoProperty object representing the property @property
6996  * in class @klass.
6997  */
6998 MonoReflectionProperty*
6999 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7000 {
7001         MonoReflectionProperty *res;
7002         static MonoClass *monoproperty_klass;
7003
7004         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7005         if (!monoproperty_klass)
7006                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
7007         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
7008         res->klass = klass;
7009         res->property = property;
7010         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7011 }
7012
7013 /*
7014  * mono_event_get_object:
7015  * @domain: an app domain
7016  * @klass: a type
7017  * @event: a event
7018  *
7019  * Return an System.Reflection.MonoEvent object representing the event @event
7020  * in class @klass.
7021  */
7022 MonoReflectionEvent*
7023 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7024 {
7025         MonoReflectionEvent *res;
7026         MonoReflectionMonoEvent *mono_event;
7027         static MonoClass *monoevent_klass;
7028
7029         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7030         if (!monoevent_klass)
7031                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7032         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
7033         mono_event->klass = klass;
7034         mono_event->event = event;
7035         res = (MonoReflectionEvent*)mono_event;
7036         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7037 }
7038
7039 /**
7040  * mono_get_reflection_missing_object:
7041  * @domain: Domain where the object lives
7042  *
7043  * Returns the System.Reflection.Missing.Value singleton object
7044  * (of type System.Reflection.Missing).
7045  *
7046  * Used as the value for ParameterInfo.DefaultValue when Optional
7047  * is present
7048  */
7049 static MonoObject *
7050 mono_get_reflection_missing_object (MonoDomain *domain)
7051 {
7052         MonoObject *obj;
7053         static MonoClassField *missing_value_field = NULL;
7054         
7055         if (!missing_value_field) {
7056                 MonoClass *missing_klass;
7057                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7058                 mono_class_init (missing_klass);
7059                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7060                 g_assert (missing_value_field);
7061         }
7062         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7063         g_assert (obj);
7064         return obj;
7065 }
7066
7067 static MonoObject*
7068 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7069 {
7070         if (!*dbnull)
7071                 *dbnull = mono_get_dbnull_object (domain);
7072         return *dbnull;
7073 }
7074
7075 static MonoObject*
7076 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7077 {
7078         if (!*reflection_missing)
7079                 *reflection_missing = mono_get_reflection_missing_object (domain);
7080         return *reflection_missing;
7081 }
7082
7083 /*
7084  * mono_param_get_objects:
7085  * @domain: an app domain
7086  * @method: a method
7087  *
7088  * Return an System.Reflection.ParameterInfo array object representing the parameters
7089  * in the method @method.
7090  */
7091 MonoArray*
7092 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7093 {
7094         static MonoClass *System_Reflection_ParameterInfo;
7095         static MonoClass *System_Reflection_ParameterInfo_array;
7096         MonoError error;
7097         MonoArray *res = NULL;
7098         MonoReflectionMethod *member = NULL;
7099         MonoReflectionParameter *param = NULL;
7100         char **names, **blobs = NULL;
7101         guint32 *types = NULL;
7102         MonoType *type = NULL;
7103         MonoObject *dbnull = NULL;
7104         MonoObject *missing = NULL;
7105         MonoMarshalSpec **mspecs;
7106         MonoMethodSignature *sig;
7107         MonoVTable *pinfo_vtable;
7108         MonoReflectionType *rt;
7109         int i;
7110
7111         if (!System_Reflection_ParameterInfo_array) {
7112                 MonoClass *klass;
7113
7114                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7115                 if (!klass)
7116                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7117
7118                 mono_memory_barrier ();
7119                 System_Reflection_ParameterInfo = klass; 
7120
7121         
7122                 klass = mono_array_class_get (klass, 1);
7123                 mono_memory_barrier ();
7124                 System_Reflection_ParameterInfo_array = klass;
7125         }
7126
7127         sig = mono_method_signature_checked (method, &error);
7128         if (!mono_error_ok (&error))
7129                 mono_error_raise_exception (&error);
7130
7131         if (!sig->param_count) {
7132                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7133                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7134
7135                 return res;
7136         }
7137
7138         /* Note: the cache is based on the address of the signature into the method
7139          * since we already cache MethodInfos with the method as keys.
7140          */
7141         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7142
7143         member = mono_method_get_object (domain, method, refclass);
7144         names = g_new (char *, sig->param_count);
7145         mono_method_get_param_names (method, (const char **) names);
7146
7147         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7148         mono_method_get_marshal_info (method, mspecs);
7149
7150         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7151         mono_error_raise_exception (&error); /* FIXME don't raise here */
7152
7153         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7154         for (i = 0; i < sig->param_count; ++i) {
7155                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7156                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7157
7158                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7159                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7160
7161                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7162
7163                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7164
7165                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7166
7167                 param->PositionImpl = i;
7168                 param->AttrsImpl = sig->params [i]->attrs;
7169
7170                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7171                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7172                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7173                         else
7174                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7175                 } else {
7176
7177                         if (!blobs) {
7178                                 blobs = g_new0 (char *, sig->param_count);
7179                                 types = g_new0 (guint32, sig->param_count);
7180                                 get_default_param_value_blobs (method, blobs, types); 
7181                         }
7182
7183                         /* Build MonoType for the type from the Constant Table */
7184                         if (!type)
7185                                 type = g_new0 (MonoType, 1);
7186                         type->type = (MonoTypeEnum)types [i];
7187                         type->data.klass = NULL;
7188                         if (types [i] == MONO_TYPE_CLASS)
7189                                 type->data.klass = mono_defaults.object_class;
7190                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7191                                 /* For enums, types [i] contains the base type */
7192
7193                                         type->type = MONO_TYPE_VALUETYPE;
7194                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7195                         } else
7196                                 type->data.klass = mono_class_from_mono_type (type);
7197
7198                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7199
7200                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7201                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7202                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7203                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7204                                 else
7205                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7206                         }
7207                         
7208                 }
7209
7210                 if (mspecs [i + 1])
7211                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7212                 
7213                 mono_array_setref (res, i, param);
7214         }
7215         g_free (names);
7216         g_free (blobs);
7217         g_free (types);
7218         g_free (type);
7219
7220         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7221                 if (mspecs [i])
7222                         mono_metadata_free_marshal_spec (mspecs [i]);
7223         g_free (mspecs);
7224         
7225         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7226 }
7227
7228 MonoArray*
7229 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7230 {
7231         return mono_param_get_objects_internal (domain, method, NULL);
7232 }
7233
7234 /*
7235  * mono_method_body_get_object:
7236  * @domain: an app domain
7237  * @method: a method
7238  *
7239  * Return an System.Reflection.MethodBody object representing the method @method.
7240  */
7241 MonoReflectionMethodBody*
7242 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7243 {
7244         static MonoClass *System_Reflection_MethodBody = NULL;
7245         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7246         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7247         MonoError error;
7248         MonoReflectionMethodBody *ret;
7249         MonoMethodHeader *header;
7250         MonoImage *image;
7251         MonoReflectionType *rt;
7252         guint32 method_rva, local_var_sig_token;
7253     char *ptr;
7254         unsigned char format, flags;
7255         int i;
7256
7257         /* for compatibility with .net */
7258     if (method_is_dynamic (method))
7259         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7260
7261         if (!System_Reflection_MethodBody)
7262                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7263         if (!System_Reflection_LocalVariableInfo)
7264                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7265         if (!System_Reflection_ExceptionHandlingClause)
7266                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7267
7268         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7269
7270         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7271                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7272             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7273                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7274             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7275                 return NULL;
7276
7277         image = method->klass->image;
7278         header = mono_method_get_header (method);
7279
7280         if (!image_is_dynamic (image)) {
7281                 /* Obtain local vars signature token */
7282                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7283                 ptr = mono_image_rva_map (image, method_rva);
7284                 flags = *(const unsigned char *) ptr;
7285                 format = flags & METHOD_HEADER_FORMAT_MASK;
7286                 switch (format){
7287                 case METHOD_HEADER_TINY_FORMAT:
7288                         local_var_sig_token = 0;
7289                         break;
7290                 case METHOD_HEADER_FAT_FORMAT:
7291                         ptr += 2;
7292                         ptr += 2;
7293                         ptr += 4;
7294                         local_var_sig_token = read32 (ptr);
7295                         break;
7296                 default:
7297                         g_assert_not_reached ();
7298                 }
7299         } else
7300                 local_var_sig_token = 0; //FIXME
7301
7302         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7303
7304         ret->init_locals = header->init_locals;
7305         ret->max_stack = header->max_stack;
7306         ret->local_var_sig_token = local_var_sig_token;
7307         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7308         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7309
7310         /* Locals */
7311         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7312         for (i = 0; i < header->num_locals; ++i) {
7313                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7314
7315                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7316                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7317
7318                 MONO_OBJECT_SETREF (info, local_type, rt);
7319
7320                 info->is_pinned = header->locals [i]->pinned;
7321                 info->local_index = i;
7322                 mono_array_setref (ret->locals, i, info);
7323         }
7324
7325         /* Exceptions */
7326         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7327         for (i = 0; i < header->num_clauses; ++i) {
7328                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7329                 MonoExceptionClause *clause = &header->clauses [i];
7330
7331                 info->flags = clause->flags;
7332                 info->try_offset = clause->try_offset;
7333                 info->try_length = clause->try_len;
7334                 info->handler_offset = clause->handler_offset;
7335                 info->handler_length = clause->handler_len;
7336                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7337                         info->filter_offset = clause->data.filter_offset;
7338                 else if (clause->data.catch_class) {
7339                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7340                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7341
7342                         MONO_OBJECT_SETREF (info, catch_type, rt);
7343                 }
7344
7345                 mono_array_setref (ret->clauses, i, info);
7346         }
7347
7348         mono_metadata_free_mh (header);
7349         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7350         return ret;
7351 }
7352
7353 /**
7354  * mono_get_dbnull_object:
7355  * @domain: Domain where the object lives
7356  *
7357  * Returns the System.DBNull.Value singleton object
7358  *
7359  * Used as the value for ParameterInfo.DefaultValue 
7360  */
7361 MonoObject *
7362 mono_get_dbnull_object (MonoDomain *domain)
7363 {
7364         MonoObject *obj;
7365         static MonoClassField *dbnull_value_field = NULL;
7366         
7367         if (!dbnull_value_field) {
7368                 MonoClass *dbnull_klass;
7369                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7370                 mono_class_init (dbnull_klass);
7371                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7372                 g_assert (dbnull_value_field);
7373         }
7374         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7375         g_assert (obj);
7376         return obj;
7377 }
7378
7379 static void
7380 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7381 {
7382         guint32 param_index, i, lastp, crow = 0;
7383         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7384         gint32 idx;
7385
7386         MonoClass *klass = method->klass;
7387         MonoImage *image = klass->image;
7388         MonoMethodSignature *methodsig = mono_method_signature (method);
7389
7390         MonoTableInfo *constt;
7391         MonoTableInfo *methodt;
7392         MonoTableInfo *paramt;
7393
7394         if (!methodsig->param_count)
7395                 return;
7396
7397         mono_class_init (klass);
7398
7399         if (image_is_dynamic (klass->image)) {
7400                 MonoReflectionMethodAux *aux;
7401                 if (method->is_inflated)
7402                         method = ((MonoMethodInflated*)method)->declaring;
7403                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7404                 if (aux && aux->param_defaults) {
7405                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7406                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7407                 }
7408                 return;
7409         }
7410
7411         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7412         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7413         constt = &image->tables [MONO_TABLE_CONSTANT];
7414
7415         idx = mono_method_get_index (method) - 1;
7416         g_assert (idx != -1);
7417
7418         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7419         if (idx + 1 < methodt->rows)
7420                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7421         else
7422                 lastp = paramt->rows + 1;
7423
7424         for (i = param_index; i < lastp; ++i) {
7425                 guint32 paramseq;
7426
7427                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7428                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7429
7430                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7431                         continue;
7432
7433                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7434                 if (!crow) {
7435                         continue;
7436                 }
7437         
7438                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7439                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7440                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7441         }
7442
7443         return;
7444 }
7445
7446 MonoObject *
7447 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7448 {
7449         void *retval;
7450         MonoClass *klass;
7451         MonoObject *object;
7452         MonoType *basetype = type;
7453
7454         if (!blob)
7455                 return NULL;
7456         
7457         klass = mono_class_from_mono_type (type);
7458         if (klass->valuetype) {
7459                 object = mono_object_new (domain, klass);
7460                 retval = ((gchar *) object + sizeof (MonoObject));
7461                 if (klass->enumtype)
7462                         basetype = mono_class_enum_basetype (klass);
7463         } else {
7464                 retval = &object;
7465         }
7466                         
7467         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7468                 return object;
7469         else
7470                 return NULL;
7471 }
7472
7473 static int
7474 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7475         int found_sep;
7476         char *s;
7477         gboolean quoted = FALSE;
7478
7479         memset (assembly, 0, sizeof (MonoAssemblyName));
7480         assembly->culture = "";
7481         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7482
7483         if (*p == '"') {
7484                 quoted = TRUE;
7485                 p++;
7486         }
7487         assembly->name = p;
7488         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7489                 p++;
7490         if (quoted) {
7491                 if (*p != '"')
7492                         return 1;
7493                 *p = 0;
7494                 p++;
7495         }
7496         if (*p != ',')
7497                 return 1;
7498         *p = 0;
7499         /* Remove trailing whitespace */
7500         s = p - 1;
7501         while (*s && g_ascii_isspace (*s))
7502                 *s-- = 0;
7503         p ++;
7504         while (g_ascii_isspace (*p))
7505                 p++;
7506         while (*p) {
7507                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7508                         p += 8;
7509                         assembly->major = strtoul (p, &s, 10);
7510                         if (s == p || *s != '.')
7511                                 return 1;
7512                         p = ++s;
7513                         assembly->minor = strtoul (p, &s, 10);
7514                         if (s == p || *s != '.')
7515                                 return 1;
7516                         p = ++s;
7517                         assembly->build = strtoul (p, &s, 10);
7518                         if (s == p || *s != '.')
7519                                 return 1;
7520                         p = ++s;
7521                         assembly->revision = strtoul (p, &s, 10);
7522                         if (s == p)
7523                                 return 1;
7524                         p = s;
7525                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7526                         p += 8;
7527                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7528                                 assembly->culture = "";
7529                                 p += 7;
7530                         } else {
7531                                 assembly->culture = p;
7532                                 while (*p && *p != ',') {
7533                                         p++;
7534                                 }
7535                         }
7536                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7537                         p += 15;
7538                         if (strncmp (p, "null", 4) == 0) {
7539                                 p += 4;
7540                         } else {
7541                                 int len;
7542                                 gchar *start = p;
7543                                 while (*p && *p != ',') {
7544                                         p++;
7545                                 }
7546                                 len = (p - start + 1);
7547                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7548                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7549                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7550                         }
7551                 } else {
7552                         while (*p && *p != ',')
7553                                 p++;
7554                 }
7555                 found_sep = 0;
7556                 while (g_ascii_isspace (*p) || *p == ',') {
7557                         *p++ = 0;
7558                         found_sep = 1;
7559                         continue;
7560                 }
7561                 /* failed */
7562                 if (!found_sep)
7563                         return 1;
7564         }
7565
7566         return 0;
7567 }
7568
7569 /*
7570  * mono_reflection_parse_type:
7571  * @name: type name
7572  *
7573  * Parse a type name as accepted by the GetType () method and output the info
7574  * extracted in the info structure.
7575  * the name param will be mangled, so, make a copy before passing it to this function.
7576  * The fields in info will be valid until the memory pointed to by name is valid.
7577  *
7578  * See also mono_type_get_name () below.
7579  *
7580  * Returns: 0 on parse error.
7581  */
7582 static int
7583 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7584                              MonoTypeNameParse *info)
7585 {
7586         char *start, *p, *w, *last_point, *startn;
7587         int in_modifiers = 0;
7588         int isbyref = 0, rank = 0, isptr = 0;
7589
7590         start = p = w = name;
7591
7592         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7593         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7594         info->name = info->name_space = NULL;
7595         info->nested = NULL;
7596         info->modifiers = NULL;
7597         info->type_arguments = NULL;
7598
7599         /* last_point separates the namespace from the name */
7600         last_point = NULL;
7601         /* Skips spaces */
7602         while (*p == ' ') p++, start++, w++, name++;
7603
7604         while (*p) {
7605                 switch (*p) {
7606                 case '+':
7607                         *p = 0; /* NULL terminate the name */
7608                         startn = p + 1;
7609                         info->nested = g_list_append (info->nested, startn);
7610                         /* we have parsed the nesting namespace + name */
7611                         if (info->name)
7612                                 break;
7613                         if (last_point) {
7614                                 info->name_space = start;
7615                                 *last_point = 0;
7616                                 info->name = last_point + 1;
7617                         } else {
7618                                 info->name_space = (char *)"";
7619                                 info->name = start;
7620                         }
7621                         break;
7622                 case '.':
7623                         last_point = p;
7624                         break;
7625                 case '\\':
7626                         ++p;
7627                         break;
7628                 case '&':
7629                 case '*':
7630                 case '[':
7631                 case ',':
7632                 case ']':
7633                         in_modifiers = 1;
7634                         break;
7635                 default:
7636                         break;
7637                 }
7638                 if (in_modifiers)
7639                         break;
7640                 // *w++ = *p++;
7641                 p++;
7642         }
7643         
7644         if (!info->name) {
7645                 if (last_point) {
7646                         info->name_space = start;
7647                         *last_point = 0;
7648                         info->name = last_point + 1;
7649                 } else {
7650                         info->name_space = (char *)"";
7651                         info->name = start;
7652                 }
7653         }
7654         while (*p) {
7655                 switch (*p) {
7656                 case '&':
7657                         if (isbyref) /* only one level allowed by the spec */
7658                                 return 0;
7659                         isbyref = 1;
7660                         isptr = 0;
7661                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7662                         *p++ = 0;
7663                         break;
7664                 case '*':
7665                         if (isbyref) /* pointer to ref not okay */
7666                                 return 0;
7667                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7668                         isptr = 1;
7669                         *p++ = 0;
7670                         break;
7671                 case '[':
7672                         if (isbyref) /* array of ref and generic ref are not okay */
7673                                 return 0;
7674                         //Decide if it's an array of a generic argument list
7675                         *p++ = 0;
7676
7677                         if (!*p) //XXX test
7678                                 return 0;
7679                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7680                                 isptr = 0;
7681                                 rank = 1;
7682                                 while (*p) {
7683                                         if (*p == ']')
7684                                                 break;
7685                                         if (*p == ',')
7686                                                 rank++;
7687                                         else if (*p == '*') /* '*' means unknown lower bound */
7688                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7689                                         else
7690                                                 return 0;
7691                                         ++p;
7692                                 }
7693                                 if (*p++ != ']')
7694                                         return 0;
7695                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7696                         } else {
7697                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7698                                         return 0;
7699                                 isptr = 0;
7700                                 info->type_arguments = g_ptr_array_new ();
7701                                 while (*p) {
7702                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7703                                         gboolean fqname = FALSE;
7704
7705                                         g_ptr_array_add (info->type_arguments, subinfo);
7706
7707                                         while (*p == ' ') p++;
7708                                         if (*p == '[') {
7709                                                 p++;
7710                                                 fqname = TRUE;
7711                                         }
7712
7713                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7714                                                 return 0;
7715
7716                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7717                                         if (fqname && (*p != ']')) {
7718                                                 char *aname;
7719
7720                                                 if (*p != ',')
7721                                                         return 0;
7722                                                 *p++ = 0;
7723
7724                                                 aname = p;
7725                                                 while (*p && (*p != ']'))
7726                                                         p++;
7727
7728                                                 if (*p != ']')
7729                                                         return 0;
7730
7731                                                 *p++ = 0;
7732                                                 while (*aname) {
7733                                                         if (g_ascii_isspace (*aname)) {
7734                                                                 ++aname;
7735                                                                 continue;
7736                                                         }
7737                                                         break;
7738                                                 }
7739                                                 if (!*aname ||
7740                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7741                                                         return 0;
7742                                         } else if (fqname && (*p == ']')) {
7743                                                 *p++ = 0;
7744                                         }
7745                                         if (*p == ']') {
7746                                                 *p++ = 0;
7747                                                 break;
7748                                         } else if (!*p) {
7749                                                 return 0;
7750                                         }
7751                                         *p++ = 0;
7752                                 }
7753                         }
7754                         break;
7755                 case ']':
7756                         if (is_recursed)
7757                                 goto end;
7758                         return 0;
7759                 case ',':
7760                         if (is_recursed)
7761                                 goto end;
7762                         *p++ = 0;
7763                         while (*p) {
7764                                 if (g_ascii_isspace (*p)) {
7765                                         ++p;
7766                                         continue;
7767                                 }
7768                                 break;
7769                         }
7770                         if (!*p)
7771                                 return 0; /* missing assembly name */
7772                         if (!assembly_name_to_aname (&info->assembly, p))
7773                                 return 0;
7774                         break;
7775                 default:
7776                         return 0;
7777                 }
7778                 if (info->assembly.name)
7779                         break;
7780         }
7781         // *w = 0; /* terminate class name */
7782  end:
7783         if (!info->name || !*info->name)
7784                 return 0;
7785         if (endptr)
7786                 *endptr = p;
7787         /* add other consistency checks */
7788         return 1;
7789 }
7790
7791
7792 /**
7793  * mono_identifier_unescape_type_name_chars:
7794  * @identifier: the display name of a mono type
7795  *
7796  * Returns:
7797  *  The name in internal form, that is without escaping backslashes.
7798  *
7799  *  The string is modified in place!
7800  */
7801 char*
7802 mono_identifier_unescape_type_name_chars(char* identifier)
7803 {
7804         char *w, *r;
7805         if (!identifier)
7806                 return NULL;
7807         for (w = r = identifier; *r != 0; r++)
7808         {
7809                 char c = *r;
7810                 if (c == '\\') {
7811                         r++;
7812                         if (*r == 0)
7813                                 break;
7814                         c = *r;
7815                 }
7816                 *w = c;
7817                 w++;
7818         }
7819         if (w != r)
7820                 *w = 0;
7821         return identifier;
7822 }
7823
7824 void
7825 mono_identifier_unescape_info (MonoTypeNameParse* info);
7826
7827 static void
7828 unescape_each_type_argument(void* data, void* user_data)
7829 {
7830         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7831         mono_identifier_unescape_info (info);
7832 }
7833
7834 static void
7835 unescape_each_nested_name (void* data, void* user_data)
7836 {
7837         char* nested_name = (char*) data;
7838         mono_identifier_unescape_type_name_chars(nested_name);
7839 }
7840
7841 /**
7842  * mono_identifier_unescape_info:
7843  *
7844  * @info: a parsed display form of an (optionally assembly qualified) full type name.
7845  *
7846  * Returns: nothing.
7847  *
7848  * Destructively updates the info by unescaping the identifiers that
7849  * comprise the type namespace, name, nested types (if any) and
7850  * generic type arguments (if any).
7851  *
7852  * The resulting info has the names in internal form.
7853  *
7854  */
7855 void
7856 mono_identifier_unescape_info (MonoTypeNameParse *info)
7857 {
7858         if (!info)
7859                 return;
7860         mono_identifier_unescape_type_name_chars(info->name_space);
7861         mono_identifier_unescape_type_name_chars(info->name);
7862         // but don't escape info->assembly
7863         if (info->type_arguments)
7864                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7865         if (info->nested)
7866                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7867 }
7868
7869 int
7870 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7871 {
7872         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7873         if (ok) {
7874                 mono_identifier_unescape_info (info);
7875         }
7876         return ok;
7877 }
7878
7879 static MonoType*
7880 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7881 {
7882         gboolean type_resolve = FALSE;
7883         MonoType *type;
7884         MonoImage *rootimage = image;
7885
7886         if (info->assembly.name) {
7887                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7888                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7889                         /* 
7890                          * This could happen in the AOT compiler case when the search hook is not
7891                          * installed.
7892                          */
7893                         assembly = image->assembly;
7894                 if (!assembly) {
7895                         /* then we must load the assembly ourselve - see #60439 */
7896                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7897                         if (!assembly)
7898                                 return NULL;
7899                 }
7900                 image = assembly->image;
7901         } else if (!image) {
7902                 image = mono_defaults.corlib;
7903         }
7904
7905         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7906         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7907                 image = mono_defaults.corlib;
7908                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7909         }
7910
7911         return type;
7912 }
7913
7914 static MonoType*
7915 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7916 {
7917         MonoError error;
7918         MonoClass *klass;
7919         GList *mod;
7920         int modval;
7921         gboolean bounded = FALSE;
7922         
7923         if (!image)
7924                 image = mono_defaults.corlib;
7925
7926         if (!rootimage)
7927                 rootimage = mono_defaults.corlib;
7928
7929         if (ignorecase) {
7930                 MonoError error;
7931                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7932                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7933         } else {
7934                 klass = mono_class_from_name (image, info->name_space, info->name);
7935         }
7936         if (!klass)
7937                 return NULL;
7938         for (mod = info->nested; mod; mod = mod->next) {
7939                 gpointer iter = NULL;
7940                 MonoClass *parent;
7941
7942                 parent = klass;
7943                 mono_class_init (parent);
7944
7945                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7946                         char *lastp;
7947                         char *nested_name, *nested_nspace;
7948                         gboolean match = TRUE;
7949
7950                         lastp = strrchr ((const char *)mod->data, '.');
7951                         if (lastp) {
7952                                 /* Nested classes can have namespaces */
7953                                 int nspace_len;
7954
7955                                 nested_name = g_strdup (lastp + 1);
7956                                 nspace_len = lastp - (char*)mod->data;
7957                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
7958                                 memcpy (nested_nspace, mod->data, nspace_len);
7959                                 nested_nspace [nspace_len] = '\0';
7960
7961                         } else {
7962                                 nested_name = (char *)mod->data;
7963                                 nested_nspace = NULL;
7964                         }
7965
7966                         if (nested_nspace) {
7967                                 if (ignorecase) {
7968                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7969                                                 match = FALSE;
7970                                 } else {
7971                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7972                                                 match = FALSE;
7973                                 }
7974                         }
7975                         if (match) {
7976                                 if (ignorecase) {
7977                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7978                                                 match = FALSE;
7979                                 } else {
7980                                         if (strcmp (klass->name, nested_name) != 0)
7981                                                 match = FALSE;
7982                                 }
7983                         }
7984                         if (lastp) {
7985                                 g_free (nested_name);
7986                                 g_free (nested_nspace);
7987                         }
7988                         if (match)
7989                                 break;
7990                 }
7991
7992                 if (!klass)
7993                         break;
7994         }
7995         if (!klass)
7996                 return NULL;
7997
7998         if (info->type_arguments) {
7999                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8000                 MonoReflectionType *the_type;
8001                 MonoType *instance;
8002                 int i;
8003
8004                 for (i = 0; i < info->type_arguments->len; i++) {
8005                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8006
8007                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8008                         if (!type_args [i]) {
8009                                 g_free (type_args);
8010                                 return NULL;
8011                         }
8012                 }
8013
8014                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
8015                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8016
8017                 instance = mono_reflection_bind_generic_parameters (
8018                         the_type, info->type_arguments->len, type_args);
8019
8020                 g_free (type_args);
8021                 if (!instance)
8022                         return NULL;
8023
8024                 klass = mono_class_from_mono_type (instance);
8025         }
8026
8027         for (mod = info->modifiers; mod; mod = mod->next) {
8028                 modval = GPOINTER_TO_UINT (mod->data);
8029                 if (!modval) { /* byref: must be last modifier */
8030                         return &klass->this_arg;
8031                 } else if (modval == -1) {
8032                         klass = mono_ptr_class_get (&klass->byval_arg);
8033                 } else if (modval == -2) {
8034                         bounded = TRUE;
8035                 } else { /* array rank */
8036                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8037                 }
8038         }
8039
8040         return &klass->byval_arg;
8041 }
8042
8043 /*
8044  * mono_reflection_get_type:
8045  * @image: a metadata context
8046  * @info: type description structure
8047  * @ignorecase: flag for case-insensitive string compares
8048  * @type_resolve: whenever type resolve was already tried
8049  *
8050  * Build a MonoType from the type description in @info.
8051  * 
8052  */
8053
8054 MonoType*
8055 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8056         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8057 }
8058
8059 static MonoType*
8060 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8061 {
8062         MonoReflectionAssemblyBuilder *abuilder;
8063         MonoType *type;
8064         int i;
8065
8066         g_assert (assembly_is_dynamic (assembly));
8067         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8068
8069         /* Enumerate all modules */
8070
8071         type = NULL;
8072         if (abuilder->modules) {
8073                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8074                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8075                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8076                         if (type)
8077                                 break;
8078                 }
8079         }
8080
8081         if (!type && abuilder->loaded_modules) {
8082                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8083                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8084                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8085                         if (type)
8086                                 break;
8087                 }
8088         }
8089
8090         return type;
8091 }
8092         
8093 MonoType*
8094 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8095 {
8096         MonoType *type;
8097         MonoReflectionAssembly *assembly;
8098         GString *fullName;
8099         GList *mod;
8100
8101         if (image && image_is_dynamic (image))
8102                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8103         else
8104                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8105         if (type)
8106                 return type;
8107         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8108                 return NULL;
8109
8110         if (type_resolve) {
8111                 if (*type_resolve) 
8112                         return NULL;
8113                 else
8114                         *type_resolve = TRUE;
8115         }
8116         
8117         /* Reconstruct the type name */
8118         fullName = g_string_new ("");
8119         if (info->name_space && (info->name_space [0] != '\0'))
8120                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8121         else
8122                 g_string_printf (fullName, "%s", info->name);
8123         for (mod = info->nested; mod; mod = mod->next)
8124                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8125
8126         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8127         if (assembly) {
8128                 if (assembly_is_dynamic (assembly->assembly))
8129                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8130                 else
8131                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8132                                                                                                           info, ignorecase);
8133         }
8134         g_string_free (fullName, TRUE);
8135         return type;
8136 }
8137
8138 void
8139 mono_reflection_free_type_info (MonoTypeNameParse *info)
8140 {
8141         g_list_free (info->modifiers);
8142         g_list_free (info->nested);
8143
8144         if (info->type_arguments) {
8145                 int i;
8146
8147                 for (i = 0; i < info->type_arguments->len; i++) {
8148                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8149
8150                         mono_reflection_free_type_info (subinfo);
8151                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8152                         g_free (subinfo);
8153                 }
8154
8155                 g_ptr_array_free (info->type_arguments, TRUE);
8156         }
8157 }
8158
8159 /*
8160  * mono_reflection_type_from_name:
8161  * @name: type name.
8162  * @image: a metadata context (can be NULL).
8163  *
8164  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8165  * it defaults to get the type from @image or, if @image is NULL or loading
8166  * from it fails, uses corlib.
8167  * 
8168  */
8169 MonoType*
8170 mono_reflection_type_from_name (char *name, MonoImage *image)
8171 {
8172         MonoType *type = NULL;
8173         MonoTypeNameParse info;
8174         char *tmp;
8175
8176         /* Make a copy since parse_type modifies its argument */
8177         tmp = g_strdup (name);
8178         
8179         /*g_print ("requested type %s\n", str);*/
8180         if (mono_reflection_parse_type (tmp, &info)) {
8181                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8182         }
8183
8184         g_free (tmp);
8185         mono_reflection_free_type_info (&info);
8186         return type;
8187 }
8188
8189 /*
8190  * mono_reflection_get_token:
8191  *
8192  *   Return the metadata token of OBJ which should be an object
8193  * representing a metadata element.
8194  */
8195 guint32
8196 mono_reflection_get_token (MonoObject *obj)
8197 {
8198         MonoClass *klass;
8199         guint32 token = 0;
8200
8201         klass = obj->vtable->klass;
8202
8203         if (strcmp (klass->name, "MethodBuilder") == 0) {
8204                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8205
8206                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8207         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8208                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8209
8210                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8211         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8212                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8213
8214                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8215         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8216                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8217                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8218         } else if (strcmp (klass->name, "MonoType") == 0) {
8219                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8220                 MonoClass *mc = mono_class_from_mono_type (type);
8221                 if (!mono_class_init (mc))
8222                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8223
8224                 token = mc->type_token;
8225         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8226                    strcmp (klass->name, "MonoMethod") == 0 ||
8227                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8228                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8229                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8230                 if (m->method->is_inflated) {
8231                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8232                         return inflated->declaring->token;
8233                 } else {
8234                         token = m->method->token;
8235                 }
8236         } else if (strcmp (klass->name, "MonoField") == 0) {
8237                 MonoReflectionField *f = (MonoReflectionField*)obj;
8238
8239                 if (is_field_on_inst (f->field)) {
8240                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8241
8242                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8243                                 int field_index = f->field - dgclass->fields;
8244                                 MonoObject *obj;
8245
8246                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8247                                 obj = dgclass->field_objects [field_index];
8248                                 return mono_reflection_get_token (obj);
8249                         }
8250                 }
8251                 token = mono_class_get_field_token (f->field);
8252         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8253                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8254
8255                 token = mono_class_get_property_token (p->property);
8256         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8257                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8258
8259                 token = mono_class_get_event_token (p->event);
8260         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8261                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8262                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8263                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8264
8265                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8266         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8267                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8268
8269                 token = m->token;
8270         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8271                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8272         } else {
8273                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8274                 MonoException *ex = mono_get_exception_not_implemented (msg);
8275                 g_free (msg);
8276                 mono_raise_exception (ex);
8277         }
8278
8279         return token;
8280 }
8281
8282 static MonoClass*
8283 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8284 {
8285         char *n;
8286         MonoType *t;
8287         int slen = mono_metadata_decode_value (p, &p);
8288
8289         mono_error_init (error);
8290
8291         n = (char *)g_memdup (p, slen + 1);
8292         n [slen] = 0;
8293         t = mono_reflection_type_from_name (n, image);
8294         if (!t) {
8295                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8296                 /* We don't free n, it's consumed by mono_error */
8297                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8298                 return NULL;
8299         }
8300         g_free (n);
8301         p += slen;
8302         *end = p;
8303         return mono_class_from_mono_type (t);
8304 }
8305
8306 static void*
8307 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8308 {
8309         int slen, type = t->type;
8310         MonoClass *tklass = t->data.klass;
8311
8312         mono_error_init (error);
8313
8314 handle_enum:
8315         switch (type) {
8316         case MONO_TYPE_U1:
8317         case MONO_TYPE_I1:
8318         case MONO_TYPE_BOOLEAN: {
8319                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8320                 *bval = *p;
8321                 *end = p + 1;
8322                 return bval;
8323         }
8324         case MONO_TYPE_CHAR:
8325         case MONO_TYPE_U2:
8326         case MONO_TYPE_I2: {
8327                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8328                 *val = read16 (p);
8329                 *end = p + 2;
8330                 return val;
8331         }
8332 #if SIZEOF_VOID_P == 4
8333         case MONO_TYPE_U:
8334         case MONO_TYPE_I:
8335 #endif
8336         case MONO_TYPE_R4:
8337         case MONO_TYPE_U4:
8338         case MONO_TYPE_I4: {
8339                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8340                 *val = read32 (p);
8341                 *end = p + 4;
8342                 return val;
8343         }
8344 #if SIZEOF_VOID_P == 8
8345         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8346         case MONO_TYPE_I:
8347 #endif
8348         case MONO_TYPE_U8:
8349         case MONO_TYPE_I8: {
8350                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8351                 *val = read64 (p);
8352                 *end = p + 8;
8353                 return val;
8354         }
8355         case MONO_TYPE_R8: {
8356                 double *val = (double *)g_malloc (sizeof (double));
8357                 readr8 (p, val);
8358                 *end = p + 8;
8359                 return val;
8360         }
8361         case MONO_TYPE_VALUETYPE:
8362                 if (t->data.klass->enumtype) {
8363                         type = mono_class_enum_basetype (t->data.klass)->type;
8364                         goto handle_enum;
8365                 } else {
8366                         MonoClass *k =  t->data.klass;
8367                         
8368                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8369                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8370                                 *val = read64 (p);
8371                                 *end = p + 8;
8372                                 return val;
8373                         }
8374                 }
8375                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8376                 break;
8377                 
8378         case MONO_TYPE_STRING:
8379                 if (*p == (char)0xFF) {
8380                         *end = p + 1;
8381                         return NULL;
8382                 }
8383                 slen = mono_metadata_decode_value (p, &p);
8384                 *end = p + slen;
8385                 return mono_string_new_len (mono_domain_get (), p, slen);
8386         case MONO_TYPE_CLASS: {
8387                 MonoReflectionType *rt;
8388                 char *n;
8389                 MonoType *t;
8390                 if (*p == (char)0xFF) {
8391                         *end = p + 1;
8392                         return NULL;
8393                 }
8394 handle_type:
8395                 slen = mono_metadata_decode_value (p, &p);
8396                 n = (char *)g_memdup (p, slen + 1);
8397                 n [slen] = 0;
8398                 t = mono_reflection_type_from_name (n, image);
8399                 if (!t) {
8400                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8401                         /* We don't free n, it's consumed by mono_error */
8402                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8403                         return NULL;
8404                 }
8405                 g_free (n);
8406                 *end = p + slen;
8407
8408                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8409                 if (!mono_error_ok (error))
8410                         return NULL;
8411
8412                 return rt;
8413         }
8414         case MONO_TYPE_OBJECT: {
8415                 char subt = *p++;
8416                 MonoObject *obj;
8417                 MonoClass *subc = NULL;
8418                 void *val;
8419
8420                 if (subt == 0x50) {
8421                         goto handle_type;
8422                 } else if (subt == 0x0E) {
8423                         type = MONO_TYPE_STRING;
8424                         goto handle_enum;
8425                 } else if (subt == 0x1D) {
8426                         MonoType simple_type = {{0}};
8427                         int etype = *p;
8428                         p ++;
8429
8430                         type = MONO_TYPE_SZARRAY;
8431                         if (etype == 0x50) {
8432                                 tklass = mono_defaults.systemtype_class;
8433                         } else if (etype == 0x55) {
8434                                 tklass = load_cattr_enum_type (image, p, &p, error);
8435                                 if (!mono_error_ok (error))
8436                                         return NULL;
8437                         } else {
8438                                 if (etype == 0x51)
8439                                         /* See Partition II, Appendix B3 */
8440                                         etype = MONO_TYPE_OBJECT;
8441                                 simple_type.type = (MonoTypeEnum)etype;
8442                                 tklass = mono_class_from_mono_type (&simple_type);
8443                         }
8444                         goto handle_enum;
8445                 } else if (subt == 0x55) {
8446                         char *n;
8447                         MonoType *t;
8448                         slen = mono_metadata_decode_value (p, &p);
8449                         n = (char *)g_memdup (p, slen + 1);
8450                         n [slen] = 0;
8451                         t = mono_reflection_type_from_name (n, image);
8452                         if (!t) {
8453                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8454                                 /* We don't free n, it's consumed by mono_error */
8455                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8456                                 return NULL;
8457                         }
8458                         g_free (n);
8459                         p += slen;
8460                         subc = mono_class_from_mono_type (t);
8461                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8462                         MonoType simple_type = {{0}};
8463                         simple_type.type = (MonoTypeEnum)subt;
8464                         subc = mono_class_from_mono_type (&simple_type);
8465                 } else {
8466                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8467                 }
8468                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8469                 obj = NULL;
8470                 if (mono_error_ok (error)) {
8471                         obj = mono_object_new (mono_domain_get (), subc);
8472                         g_assert (!subc->has_references);
8473                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8474                 }
8475
8476                 g_free (val);
8477                 return obj;
8478         }
8479         case MONO_TYPE_SZARRAY: {
8480                 MonoArray *arr;
8481                 guint32 i, alen, basetype;
8482                 alen = read32 (p);
8483                 p += 4;
8484                 if (alen == 0xffffffff) {
8485                         *end = p;
8486                         return NULL;
8487                 }
8488                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8489                 basetype = tklass->byval_arg.type;
8490                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8491                         basetype = mono_class_enum_basetype (tklass)->type;
8492                 switch (basetype)
8493                 {
8494                         case MONO_TYPE_U1:
8495                         case MONO_TYPE_I1:
8496                         case MONO_TYPE_BOOLEAN:
8497                                 for (i = 0; i < alen; i++) {
8498                                         MonoBoolean val = *p++;
8499                                         mono_array_set (arr, MonoBoolean, i, val);
8500                                 }
8501                                 break;
8502                         case MONO_TYPE_CHAR:
8503                         case MONO_TYPE_U2:
8504                         case MONO_TYPE_I2:
8505                                 for (i = 0; i < alen; i++) {
8506                                         guint16 val = read16 (p);
8507                                         mono_array_set (arr, guint16, i, val);
8508                                         p += 2;
8509                                 }
8510                                 break;
8511                         case MONO_TYPE_R4:
8512                         case MONO_TYPE_U4:
8513                         case MONO_TYPE_I4:
8514                                 for (i = 0; i < alen; i++) {
8515                                         guint32 val = read32 (p);
8516                                         mono_array_set (arr, guint32, i, val);
8517                                         p += 4;
8518                                 }
8519                                 break;
8520                         case MONO_TYPE_R8:
8521                                 for (i = 0; i < alen; i++) {
8522                                         double val;
8523                                         readr8 (p, &val);
8524                                         mono_array_set (arr, double, i, val);
8525                                         p += 8;
8526                                 }
8527                                 break;
8528                         case MONO_TYPE_U8:
8529                         case MONO_TYPE_I8:
8530                                 for (i = 0; i < alen; i++) {
8531                                         guint64 val = read64 (p);
8532                                         mono_array_set (arr, guint64, i, val);
8533                                         p += 8;
8534                                 }
8535                                 break;
8536                         case MONO_TYPE_CLASS:
8537                         case MONO_TYPE_OBJECT:
8538                         case MONO_TYPE_STRING:
8539                         case MONO_TYPE_SZARRAY:
8540                                 for (i = 0; i < alen; i++) {
8541                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8542                                         if (!mono_error_ok (error))
8543                                                 return NULL;
8544                                         mono_array_setref (arr, i, item);
8545                                 }
8546                                 break;
8547                         default:
8548                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8549                 }
8550                 *end=p;
8551                 return arr;
8552         }
8553         default:
8554                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8555         }
8556         return NULL;
8557 }
8558
8559 static MonoObject*
8560 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8561 {
8562         static MonoClass *klass;
8563         static MonoMethod *ctor;
8564         MonoError error;
8565         MonoObject *retval;
8566         void *params [2], *unboxed;
8567
8568         if (!klass)
8569                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8570         if (!ctor)
8571                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8572         
8573         params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8574         mono_error_raise_exception (&error); /* FIXME don't raise here */
8575
8576         params [1] = val;
8577         retval = mono_object_new (mono_domain_get (), klass);
8578         unboxed = mono_object_unbox (retval);
8579         mono_runtime_invoke (ctor, unboxed, params, NULL);
8580
8581         return retval;
8582 }
8583
8584 static MonoObject*
8585 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8586 {
8587         static MonoClass *klass;
8588         static MonoMethod *ctor;
8589         MonoObject *retval;
8590         void *unboxed, *params [2];
8591
8592         if (!klass)
8593                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8594         if (!ctor)
8595                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8596
8597         params [0] = minfo;
8598         params [1] = typedarg;
8599         retval = mono_object_new (mono_domain_get (), klass);
8600         unboxed = mono_object_unbox (retval);
8601         mono_runtime_invoke (ctor, unboxed, params, NULL);
8602
8603         return retval;
8604 }
8605
8606 static gboolean
8607 type_is_reference (MonoType *type)
8608 {
8609         switch (type->type) {
8610         case MONO_TYPE_BOOLEAN:
8611         case MONO_TYPE_CHAR:
8612         case MONO_TYPE_U:
8613         case MONO_TYPE_I:
8614         case MONO_TYPE_U1:
8615         case MONO_TYPE_I1:
8616         case MONO_TYPE_U2:
8617         case MONO_TYPE_I2:
8618         case MONO_TYPE_U4:
8619         case MONO_TYPE_I4:
8620         case MONO_TYPE_U8:
8621         case MONO_TYPE_I8:
8622         case MONO_TYPE_R8:
8623         case MONO_TYPE_R4:
8624         case MONO_TYPE_VALUETYPE:
8625                 return FALSE;
8626         default:
8627                 return TRUE;
8628         }
8629 }
8630
8631 static void
8632 free_param_data (MonoMethodSignature *sig, void **params) {
8633         int i;
8634         for (i = 0; i < sig->param_count; ++i) {
8635                 if (!type_is_reference (sig->params [i]))
8636                         g_free (params [i]);
8637         }
8638 }
8639
8640 /*
8641  * Find the field index in the metadata FieldDef table.
8642  */
8643 static guint32
8644 find_field_index (MonoClass *klass, MonoClassField *field) {
8645         int i;
8646
8647         for (i = 0; i < klass->field.count; ++i) {
8648                 if (field == &klass->fields [i])
8649                         return klass->field.first + 1 + i;
8650         }
8651         return 0;
8652 }
8653
8654 /*
8655  * Find the property index in the metadata Property table.
8656  */
8657 static guint32
8658 find_property_index (MonoClass *klass, MonoProperty *property) {
8659         int i;
8660
8661         for (i = 0; i < klass->ext->property.count; ++i) {
8662                 if (property == &klass->ext->properties [i])
8663                         return klass->ext->property.first + 1 + i;
8664         }
8665         return 0;
8666 }
8667
8668 /*
8669  * Find the event index in the metadata Event table.
8670  */
8671 static guint32
8672 find_event_index (MonoClass *klass, MonoEvent *event) {
8673         int i;
8674
8675         for (i = 0; i < klass->ext->event.count; ++i) {
8676                 if (event == &klass->ext->events [i])
8677                         return klass->ext->event.first + 1 + i;
8678         }
8679         return 0;
8680 }
8681
8682 static MonoObject*
8683 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8684 {
8685         const char *p = (const char*)data;
8686         const char *named;
8687         guint32 i, j, num_named;
8688         MonoObject *attr;
8689         void *params_buf [32];
8690         void **params = NULL;
8691         MonoMethodSignature *sig;
8692         MonoObject *exc = NULL;
8693
8694         mono_error_init (error);
8695
8696         mono_class_init (method->klass);
8697
8698         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8699                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8700                 return NULL;
8701         }
8702
8703         if (len == 0) {
8704                 attr = mono_object_new (mono_domain_get (), method->klass);
8705                 mono_runtime_invoke (method, attr, NULL, NULL);
8706                 return attr;
8707         }
8708
8709         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8710                 return NULL;
8711
8712         /*g_print ("got attr %s\n", method->klass->name);*/
8713
8714         sig = mono_method_signature (method);
8715         if (sig->param_count < 32) {
8716                 params = params_buf;
8717                 memset (params, 0, sizeof (void*) * sig->param_count);
8718         } else {
8719                 /* Allocate using GC so it gets GC tracking */
8720                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8721         }
8722
8723         /* skip prolog */
8724         p += 2;
8725         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8726                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8727                 if (!mono_error_ok (error))
8728                         goto fail;
8729         }
8730
8731         named = p;
8732         attr = mono_object_new (mono_domain_get (), method->klass);
8733
8734         mono_runtime_invoke (method, attr, params, &exc);
8735         if (exc)
8736                 goto fail;
8737         num_named = read16 (named);
8738         named += 2;
8739         for (j = 0; j < num_named; j++) {
8740                 gint name_len;
8741                 char *name, named_type, data_type;
8742                 named_type = *named++;
8743                 data_type = *named++; /* type of data */
8744                 if (data_type == MONO_TYPE_SZARRAY)
8745                         data_type = *named++;
8746                 if (data_type == MONO_TYPE_ENUM) {
8747                         gint type_len;
8748                         char *type_name;
8749                         type_len = mono_metadata_decode_blob_size (named, &named);
8750                         type_name = (char *)g_malloc (type_len + 1);
8751                         memcpy (type_name, named, type_len);
8752                         type_name [type_len] = 0;
8753                         named += type_len;
8754                         /* FIXME: lookup the type and check type consistency */
8755                         g_free (type_name);
8756                 }
8757                 name_len = mono_metadata_decode_blob_size (named, &named);
8758                 name = (char *)g_malloc (name_len + 1);
8759                 memcpy (name, named, name_len);
8760                 name [name_len] = 0;
8761                 named += name_len;
8762                 if (named_type == 0x53) {
8763                         MonoClassField *field;
8764                         void *val;
8765
8766                         /* how this fail is a blackbox */
8767                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8768                         if (!field) {
8769                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8770                                 g_free (name);
8771                                 goto fail;
8772                         }
8773
8774                         val = load_cattr_value (image, field->type, named, &named, error);
8775                         if (!mono_error_ok (error)) {
8776                                 g_free (name);
8777                                 if (!type_is_reference (field->type))
8778                                         g_free (val);
8779                                 goto fail;
8780                         }
8781
8782                         mono_field_set_value (attr, field, val);
8783                         if (!type_is_reference (field->type))
8784                                 g_free (val);
8785                 } else if (named_type == 0x54) {
8786                         MonoProperty *prop;
8787                         void *pparams [1];
8788                         MonoType *prop_type;
8789
8790                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8791
8792                         if (!prop) {
8793                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8794                                 g_free (name);
8795                                 goto fail;
8796                         }
8797
8798                         if (!prop->set) {
8799                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8800                                 g_free (name);
8801                                 goto fail;
8802                         }
8803
8804                         /* can we have more that 1 arg in a custom attr named property? */
8805                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8806                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8807
8808                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8809                         if (!mono_error_ok (error)) {
8810                                 g_free (name);
8811                                 if (!type_is_reference (prop_type))
8812                                         g_free (pparams [0]);
8813                                 goto fail;
8814                         }
8815
8816
8817                         mono_property_set_value (prop, attr, pparams, NULL);
8818                         if (!type_is_reference (prop_type))
8819                                 g_free (pparams [0]);
8820                 }
8821                 g_free (name);
8822         }
8823
8824         free_param_data (method->signature, params);
8825         if (params != params_buf)
8826                 mono_gc_free_fixed (params);
8827
8828         return attr;
8829
8830 fail:
8831         free_param_data (method->signature, params);
8832         if (params != params_buf)
8833                 mono_gc_free_fixed (params);
8834         if (exc)
8835                 mono_raise_exception ((MonoException*)exc);
8836         return NULL;
8837 }
8838         
8839 /*
8840  * mono_reflection_create_custom_attr_data_args:
8841  *
8842  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8843  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8844  * NAMED_ARG_INFO will contain information about the named arguments.
8845  */
8846 void
8847 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)
8848 {
8849         MonoArray *typedargs, *namedargs;
8850         MonoClass *attrklass;
8851         MonoDomain *domain;
8852         const char *p = (const char*)data;
8853         const char *named;
8854         guint32 i, j, num_named;
8855         CattrNamedArg *arginfo = NULL;
8856
8857         *typed_args = NULL;
8858         *named_args = NULL;
8859         *named_arg_info = NULL;
8860
8861         mono_error_init (error);
8862
8863         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8864                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8865                 return;
8866         }
8867
8868         mono_class_init (method->klass);
8869         
8870         domain = mono_domain_get ();
8871
8872         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8873                 return;
8874
8875         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8876         
8877         /* skip prolog */
8878         p += 2;
8879         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8880                 MonoObject *obj;
8881                 void *val;
8882
8883                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8884                 if (!mono_error_ok (error)) {
8885                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8886                                 g_free (val);
8887                         return;
8888                 }
8889
8890                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8891                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8892                 mono_array_setref (typedargs, i, obj);
8893
8894                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8895                         g_free (val);
8896         }
8897
8898         named = p;
8899         num_named = read16 (named);
8900         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8901         named += 2;
8902         attrklass = method->klass;
8903
8904         arginfo = g_new0 (CattrNamedArg, num_named);
8905         *named_arg_info = arginfo;
8906
8907         for (j = 0; j < num_named; j++) {
8908                 gint name_len;
8909                 char *name, named_type, data_type;
8910                 named_type = *named++;
8911                 data_type = *named++; /* type of data */
8912                 if (data_type == MONO_TYPE_SZARRAY)
8913                         data_type = *named++;
8914                 if (data_type == MONO_TYPE_ENUM) {
8915                         gint type_len;
8916                         char *type_name;
8917                         type_len = mono_metadata_decode_blob_size (named, &named);
8918                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8919                                 goto fail;
8920
8921                         type_name = (char *)g_malloc (type_len + 1);
8922                         memcpy (type_name, named, type_len);
8923                         type_name [type_len] = 0;
8924                         named += type_len;
8925                         /* FIXME: lookup the type and check type consistency */
8926                         g_free (type_name);
8927                 }
8928                 name_len = mono_metadata_decode_blob_size (named, &named);
8929                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8930                         goto fail;
8931                 name = (char *)g_malloc (name_len + 1);
8932                 memcpy (name, named, name_len);
8933                 name [name_len] = 0;
8934                 named += name_len;
8935                 if (named_type == 0x53) {
8936                         MonoObject *obj;
8937                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8938                         void *val;
8939
8940                         if (!field) {
8941                                 g_free (name);
8942                                 goto fail;
8943                         }
8944
8945                         arginfo [j].type = field->type;
8946                         arginfo [j].field = field;
8947
8948                         val = load_cattr_value (image, field->type, named, &named, error);
8949                         if (!mono_error_ok (error)) {
8950                                 if (!type_is_reference (field->type))
8951                                         g_free (val);
8952                                 g_free (name);
8953                                 return;
8954                         }
8955
8956                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8957                         mono_array_setref (namedargs, j, obj);
8958                         if (!type_is_reference (field->type))
8959                                 g_free (val);
8960                 } else if (named_type == 0x54) {
8961                         MonoObject *obj;
8962                         MonoType *prop_type;
8963                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8964                         void *val;
8965
8966                         if (!prop || !prop->set) {
8967                                 g_free (name);
8968                                 goto fail;
8969                         }
8970
8971                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8972                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8973
8974                         arginfo [j].type = prop_type;
8975                         arginfo [j].prop = prop;
8976
8977                         val = load_cattr_value (image, prop_type, named, &named, error);
8978                         if (!mono_error_ok (error)) {
8979                                 if (!type_is_reference (prop_type))
8980                                         g_free (val);
8981                                 g_free (name);
8982                                 return;
8983                         }
8984
8985                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8986                         mono_array_setref (namedargs, j, obj);
8987                         if (!type_is_reference (prop_type))
8988                                 g_free (val);
8989                 }
8990                 g_free (name);
8991         }
8992
8993         *typed_args = typedargs;
8994         *named_args = namedargs;
8995         return;
8996 fail:
8997         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8998         g_free (arginfo);
8999         *named_arg_info = NULL;
9000 }
9001
9002 void
9003 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9004 {
9005         MonoDomain *domain;
9006         MonoArray *typedargs, *namedargs;
9007         MonoImage *image;
9008         MonoMethod *method;
9009         CattrNamedArg *arginfo = NULL;
9010         MonoError error;
9011         int i;
9012
9013         mono_error_init (&error);
9014
9015         *ctor_args = NULL;
9016         *named_args = NULL;
9017
9018         if (len == 0)
9019                 return;
9020
9021         image = assembly->assembly->image;
9022         method = ref_method->method;
9023         domain = mono_object_domain (ref_method);
9024
9025         if (!mono_class_init (method->klass))
9026                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9027
9028         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9029         if (!mono_error_ok (&error))
9030                 goto leave;
9031
9032         if (mono_loader_get_last_error ()) {
9033                 mono_error_set_from_loader_error (&error);
9034                 goto leave;
9035         }
9036
9037         if (!typedargs || !namedargs)
9038                 goto leave;
9039
9040         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9041                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9042                 MonoObject *typedarg;
9043
9044                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9045                 mono_array_setref (typedargs, i, typedarg);
9046         }
9047
9048         for (i = 0; i < mono_array_length (namedargs); ++i) {
9049                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9050                 MonoObject *typedarg, *namedarg, *minfo;
9051
9052                 if (arginfo [i].prop)
9053                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9054                 else {
9055                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9056                         if (!mono_error_ok (&error))
9057                                 goto leave;
9058                 }
9059
9060                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9061                 namedarg = create_cattr_named_arg (minfo, typedarg);
9062
9063                 mono_array_setref (namedargs, i, namedarg);
9064         }
9065
9066         *ctor_args = typedargs;
9067         *named_args = namedargs;
9068 leave:
9069         g_free (arginfo);
9070         mono_error_raise_exception (&error);
9071
9072 }
9073
9074 static MonoObject*
9075 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9076 {
9077         static MonoMethod *ctor;
9078         MonoDomain *domain;
9079         MonoObject *attr;
9080         void *params [4];
9081
9082         g_assert (image->assembly);
9083
9084         if (!ctor)
9085                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9086
9087         domain = mono_domain_get ();
9088         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
9089         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
9090         params [1] = mono_assembly_get_object (domain, image->assembly);
9091         params [2] = (gpointer)&cattr->data;
9092         params [3] = &cattr->data_size;
9093         mono_runtime_invoke (ctor, attr, params, NULL);
9094         return attr;
9095 }
9096
9097 static MonoArray*
9098 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9099 {
9100         MonoArray *result;
9101         MonoObject *attr;
9102         int i, n;
9103
9104         mono_error_init (error);
9105
9106         n = 0;
9107         for (i = 0; i < cinfo->num_attrs; ++i) {
9108                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9109                         n ++;
9110         }
9111
9112         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9113         n = 0;
9114         for (i = 0; i < cinfo->num_attrs; ++i) {
9115                 if (!cinfo->attrs [i].ctor)
9116                         /* The cattr type is not finished yet */
9117                         /* We should include the type name but cinfo doesn't contain it */
9118                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9119                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9120                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9121                         if (!mono_error_ok (error))
9122                                 return result;
9123                         mono_array_setref (result, n, attr);
9124                         n ++;
9125                 }
9126         }
9127         return result;
9128 }
9129
9130 MonoArray*
9131 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9132 {
9133         MonoError error;
9134         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9135         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9136
9137         return result;
9138 }
9139
9140 static MonoArray*
9141 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9142 {
9143         MonoArray *result;
9144         MonoObject *attr;
9145         int i;
9146         
9147         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9148         for (i = 0; i < cinfo->num_attrs; ++i) {
9149                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9150                 mono_array_setref (result, i, attr);
9151         }
9152         return result;
9153 }
9154
9155 /**
9156  * mono_custom_attrs_from_index:
9157  *
9158  * Returns: NULL if no attributes are found or if a loading error occurs.
9159  */
9160 MonoCustomAttrInfo*
9161 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9162 {
9163         guint32 mtoken, i, len;
9164         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9165         MonoTableInfo *ca;
9166         MonoCustomAttrInfo *ainfo;
9167         GList *tmp, *list = NULL;
9168         const char *data;
9169         MonoCustomAttrEntry* attr;
9170
9171         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9172
9173         i = mono_metadata_custom_attrs_from_index (image, idx);
9174         if (!i)
9175                 return NULL;
9176         i --;
9177         while (i < ca->rows) {
9178                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9179                         break;
9180                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9181                 ++i;
9182         }
9183         len = g_list_length (list);
9184         if (!len)
9185                 return NULL;
9186         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9187         ainfo->num_attrs = len;
9188         ainfo->image = image;
9189         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9190                 MonoError error;
9191                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9192                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9193                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9194                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9195                         mtoken |= MONO_TOKEN_METHOD_DEF;
9196                         break;
9197                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9198                         mtoken |= MONO_TOKEN_MEMBER_REF;
9199                         break;
9200                 default:
9201                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9202                         break;
9203                 }
9204                 attr = &ainfo->attrs [i - 1];
9205                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9206                 if (!attr->ctor) {
9207                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9208                         mono_loader_set_error_from_mono_error (&error);
9209                         g_list_free (list);
9210                         g_free (ainfo);
9211                         return NULL;
9212                 }
9213
9214                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9215                         /*FIXME raising an exception here doesn't make any sense*/
9216                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9217                         g_list_free (list);
9218                         g_free (ainfo);
9219                         return NULL;
9220                 }
9221                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9222                 attr->data_size = mono_metadata_decode_value (data, &data);
9223                 attr->data = (guchar*)data;
9224         }
9225         g_list_free (list);
9226
9227         return ainfo;
9228 }
9229
9230 MonoCustomAttrInfo*
9231 mono_custom_attrs_from_method (MonoMethod *method)
9232 {
9233         guint32 idx;
9234
9235         /*
9236          * An instantiated method has the same cattrs as the generic method definition.
9237          *
9238          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9239          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9240          */
9241         if (method->is_inflated)
9242                 method = ((MonoMethodInflated *) method)->declaring;
9243         
9244         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9245                 return lookup_custom_attr (method->klass->image, method);
9246
9247         if (!method->token)
9248                 /* Synthetic methods */
9249                 return NULL;
9250
9251         idx = mono_method_get_index (method);
9252         idx <<= MONO_CUSTOM_ATTR_BITS;
9253         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9254         return mono_custom_attrs_from_index (method->klass->image, idx);
9255 }
9256
9257 MonoCustomAttrInfo*
9258 mono_custom_attrs_from_class (MonoClass *klass)
9259 {
9260         guint32 idx;
9261
9262         if (klass->generic_class)
9263                 klass = klass->generic_class->container_class;
9264
9265         if (image_is_dynamic (klass->image))
9266                 return lookup_custom_attr (klass->image, klass);
9267
9268         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9269                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9270                 idx <<= MONO_CUSTOM_ATTR_BITS;
9271                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9272         } else {
9273                 idx = mono_metadata_token_index (klass->type_token);
9274                 idx <<= MONO_CUSTOM_ATTR_BITS;
9275                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9276         }
9277         return mono_custom_attrs_from_index (klass->image, idx);
9278 }
9279
9280 MonoCustomAttrInfo*
9281 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9282 {
9283         guint32 idx;
9284         
9285         if (image_is_dynamic (assembly->image))
9286                 return lookup_custom_attr (assembly->image, assembly);
9287         idx = 1; /* there is only one assembly */
9288         idx <<= MONO_CUSTOM_ATTR_BITS;
9289         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9290         return mono_custom_attrs_from_index (assembly->image, idx);
9291 }
9292
9293 static MonoCustomAttrInfo*
9294 mono_custom_attrs_from_module (MonoImage *image)
9295 {
9296         guint32 idx;
9297         
9298         if (image_is_dynamic (image))
9299                 return lookup_custom_attr (image, image);
9300         idx = 1; /* there is only one module */
9301         idx <<= MONO_CUSTOM_ATTR_BITS;
9302         idx |= MONO_CUSTOM_ATTR_MODULE;
9303         return mono_custom_attrs_from_index (image, idx);
9304 }
9305
9306 MonoCustomAttrInfo*
9307 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9308 {
9309         guint32 idx;
9310         
9311         if (image_is_dynamic (klass->image)) {
9312                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9313                 return lookup_custom_attr (klass->image, property);
9314         }
9315         idx = find_property_index (klass, property);
9316         idx <<= MONO_CUSTOM_ATTR_BITS;
9317         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9318         return mono_custom_attrs_from_index (klass->image, idx);
9319 }
9320
9321 MonoCustomAttrInfo*
9322 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9323 {
9324         guint32 idx;
9325         
9326         if (image_is_dynamic (klass->image)) {
9327                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9328                 return lookup_custom_attr (klass->image, event);
9329         }
9330         idx = find_event_index (klass, event);
9331         idx <<= MONO_CUSTOM_ATTR_BITS;
9332         idx |= MONO_CUSTOM_ATTR_EVENT;
9333         return mono_custom_attrs_from_index (klass->image, idx);
9334 }
9335
9336 MonoCustomAttrInfo*
9337 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9338 {
9339         guint32 idx;
9340         if (image_is_dynamic (klass->image)) {
9341                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9342                 return lookup_custom_attr (klass->image, field);
9343         }
9344         idx = find_field_index (klass, field);
9345         idx <<= MONO_CUSTOM_ATTR_BITS;
9346         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9347         return mono_custom_attrs_from_index (klass->image, idx);
9348 }
9349
9350 /**
9351  * mono_custom_attrs_from_param:
9352  * @method: handle to the method that we want to retrieve custom parameter information from
9353  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9354  *
9355  * The result must be released with mono_custom_attrs_free().
9356  *
9357  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9358  */
9359 MonoCustomAttrInfo*
9360 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9361 {
9362         MonoTableInfo *ca;
9363         guint32 i, idx, method_index;
9364         guint32 param_list, param_last, param_pos, found;
9365         MonoImage *image;
9366         MonoReflectionMethodAux *aux;
9367
9368         /*
9369          * An instantiated method has the same cattrs as the generic method definition.
9370          *
9371          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9372          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9373          */
9374         if (method->is_inflated)
9375                 method = ((MonoMethodInflated *) method)->declaring;
9376
9377         if (image_is_dynamic (method->klass->image)) {
9378                 MonoCustomAttrInfo *res, *ainfo;
9379                 int size;
9380
9381                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9382                 if (!aux || !aux->param_cattr)
9383                         return NULL;
9384
9385                 /* Need to copy since it will be freed later */
9386                 ainfo = aux->param_cattr [param];
9387                 if (!ainfo)
9388                         return NULL;
9389                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9390                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9391                 memcpy (res, ainfo, size);
9392                 return res;
9393         }
9394
9395         image = method->klass->image;
9396         method_index = mono_method_get_index (method);
9397         if (!method_index)
9398                 return NULL;
9399         ca = &image->tables [MONO_TABLE_METHOD];
9400
9401         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9402         if (method_index == ca->rows) {
9403                 ca = &image->tables [MONO_TABLE_PARAM];
9404                 param_last = ca->rows + 1;
9405         } else {
9406                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9407                 ca = &image->tables [MONO_TABLE_PARAM];
9408         }
9409         found = FALSE;
9410         for (i = param_list; i < param_last; ++i) {
9411                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9412                 if (param_pos == param) {
9413                         found = TRUE;
9414                         break;
9415                 }
9416         }
9417         if (!found)
9418                 return NULL;
9419         idx = i;
9420         idx <<= MONO_CUSTOM_ATTR_BITS;
9421         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9422         return mono_custom_attrs_from_index (image, idx);
9423 }
9424
9425 gboolean
9426 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9427 {
9428         int i;
9429         MonoClass *klass;
9430         for (i = 0; i < ainfo->num_attrs; ++i) {
9431                 klass = ainfo->attrs [i].ctor->klass;
9432                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9433                         return TRUE;
9434         }
9435         return FALSE;
9436 }
9437
9438 MonoObject*
9439 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9440 {
9441         MonoError error;
9442         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9443         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9444         return res;
9445 }
9446
9447 MonoObject*
9448 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9449 {
9450         int i, attr_index;
9451         MonoClass *klass;
9452         MonoArray *attrs;
9453
9454         mono_error_init (error);
9455
9456         attr_index = -1;
9457         for (i = 0; i < ainfo->num_attrs; ++i) {
9458                 klass = ainfo->attrs [i].ctor->klass;
9459                 if (mono_class_has_parent (klass, attr_klass)) {
9460                         attr_index = i;
9461                         break;
9462                 }
9463         }
9464         if (attr_index == -1)
9465                 return NULL;
9466
9467         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9468         if (!mono_error_ok (error))
9469                 return NULL;
9470         return mono_array_get (attrs, MonoObject*, attr_index);
9471 }
9472
9473 /*
9474  * mono_reflection_get_custom_attrs_info:
9475  * @obj: a reflection object handle
9476  *
9477  * Return the custom attribute info for attributes defined for the
9478  * reflection handle @obj. The objects.
9479  *
9480  * FIXME this function leaks like a sieve for SRE objects.
9481  */
9482 MonoCustomAttrInfo*
9483 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9484 {
9485         MonoClass *klass;
9486         MonoCustomAttrInfo *cinfo = NULL;
9487         
9488         klass = obj->vtable->klass;
9489         if (klass == mono_defaults.monotype_class) {
9490                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9491                 klass = mono_class_from_mono_type (type);
9492                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9493                 cinfo = mono_custom_attrs_from_class (klass);
9494         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9495                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9496                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9497         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9498                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9499                 cinfo = mono_custom_attrs_from_module (module->image);
9500         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9501                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9502                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9503         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9504                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9505                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9506         } else if (strcmp ("MonoField", klass->name) == 0) {
9507                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9508                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9509         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9510                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9511                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9512         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9513                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9514                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9515         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9516                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9517                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9518                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9519                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9520                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9521                 } else if (is_sr_mono_property (member_class)) {
9522                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9523                         MonoMethod *method;
9524                         if (!(method = prop->property->get))
9525                                 method = prop->property->set;
9526                         g_assert (method);
9527
9528                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9529                 } 
9530 #ifndef DISABLE_REFLECTION_EMIT
9531                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9532                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9533                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9534                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9535                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9536                         MonoMethod *method = NULL;
9537                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9538                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9539                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9540                                 method = ((MonoReflectionMethod *)c->cb)->method;
9541                         else
9542                                 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));
9543
9544                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9545                 } 
9546 #endif
9547                 else {
9548                         char *type_name = mono_type_get_full_name (member_class);
9549                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9550                         MonoException *ex = mono_get_exception_not_supported  (msg);
9551                         g_free (type_name);
9552                         g_free (msg);
9553                         mono_raise_exception (ex);
9554                 }
9555         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9556                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9557                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9558         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9559                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9560                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9561         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9562                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9563                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9564         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9565                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9566                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9567         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9568                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9569                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9570         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9571                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9572                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9573         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9574                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9575                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9576         } else { /* handle other types here... */
9577                 g_error ("get custom attrs not yet supported for %s", klass->name);
9578         }
9579
9580         return cinfo;
9581 }
9582
9583 /*
9584  * mono_reflection_get_custom_attrs_by_type:
9585  * @obj: a reflection object handle
9586  *
9587  * Return an array with all the custom attributes defined of the
9588  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9589  * of that type are returned. The objects are fully build. Return NULL if a loading error
9590  * occurs.
9591  */
9592 MonoArray*
9593 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9594 {
9595         MonoArray *result;
9596         MonoCustomAttrInfo *cinfo;
9597
9598         mono_error_init (error);
9599
9600         cinfo = mono_reflection_get_custom_attrs_info (obj);
9601         if (cinfo) {
9602                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9603                 if (!cinfo->cached)
9604                         mono_custom_attrs_free (cinfo);
9605         } else {
9606                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9607                 if (mono_loader_get_last_error ())
9608                         return NULL;
9609                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9610         }
9611
9612         return result;
9613 }
9614
9615 /*
9616  * mono_reflection_get_custom_attrs:
9617  * @obj: a reflection object handle
9618  *
9619  * Return an array with all the custom attributes defined of the
9620  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9621  * occurs.
9622  */
9623 MonoArray*
9624 mono_reflection_get_custom_attrs (MonoObject *obj)
9625 {
9626         MonoError error;
9627
9628         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9629 }
9630
9631 /*
9632  * mono_reflection_get_custom_attrs_data:
9633  * @obj: a reflection obj handle
9634  *
9635  * Returns an array of System.Reflection.CustomAttributeData,
9636  * which include information about attributes reflected on
9637  * types loaded using the Reflection Only methods
9638  */
9639 MonoArray*
9640 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9641 {
9642         MonoArray *result;
9643         MonoCustomAttrInfo *cinfo;
9644
9645         cinfo = mono_reflection_get_custom_attrs_info (obj);
9646         if (cinfo) {
9647                 result = mono_custom_attrs_data_construct (cinfo);
9648                 if (!cinfo->cached)
9649                         mono_custom_attrs_free (cinfo);
9650         } else
9651                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9652
9653         return result;
9654 }
9655
9656 static MonoReflectionType*
9657 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9658 {
9659         static MonoMethod *method_get_underlying_system_type = NULL;
9660         MonoMethod *usertype_method;
9661
9662         if (!method_get_underlying_system_type)
9663                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9664         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9665         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9666 }
9667
9668
9669 static gboolean
9670 is_corlib_type (MonoClass *klass)
9671 {
9672         return klass->image == mono_defaults.corlib;
9673 }
9674
9675 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9676         static MonoClass *cached_class; \
9677         if (cached_class) \
9678                 return cached_class == _class; \
9679         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9680                 cached_class = _class; \
9681                 return TRUE; \
9682         } \
9683         return FALSE; \
9684 } while (0) \
9685
9686
9687 #ifndef DISABLE_REFLECTION_EMIT
9688 static gboolean
9689 is_sre_array (MonoClass *klass)
9690 {
9691         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9692 }
9693
9694 static gboolean
9695 is_sre_byref (MonoClass *klass)
9696 {
9697         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9698 }
9699
9700 static gboolean
9701 is_sre_pointer (MonoClass *klass)
9702 {
9703         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9704 }
9705
9706 static gboolean
9707 is_sre_generic_instance (MonoClass *klass)
9708 {
9709         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9710 }
9711
9712 static gboolean
9713 is_sre_type_builder (MonoClass *klass)
9714 {
9715         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9716 }
9717
9718 static gboolean
9719 is_sre_method_builder (MonoClass *klass)
9720 {
9721         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9722 }
9723
9724 static gboolean
9725 is_sre_ctor_builder (MonoClass *klass)
9726 {
9727         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9728 }
9729
9730 static gboolean
9731 is_sre_field_builder (MonoClass *klass)
9732 {
9733         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9734 }
9735
9736 static gboolean
9737 is_sre_method_on_tb_inst (MonoClass *klass)
9738 {
9739         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9740 }
9741
9742 static gboolean
9743 is_sre_ctor_on_tb_inst (MonoClass *klass)
9744 {
9745         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9746 }
9747
9748 MonoType*
9749 mono_reflection_type_get_handle (MonoReflectionType* ref)
9750 {
9751         MonoClass *klass;
9752         if (!ref)
9753                 return NULL;
9754         if (ref->type)
9755                 return ref->type;
9756
9757         if (is_usertype (ref)) {
9758                 ref = mono_reflection_type_get_underlying_system_type (ref);
9759                 if (ref == NULL || is_usertype (ref))
9760                         return NULL;
9761                 if (ref->type)
9762                         return ref->type;
9763         }
9764
9765         klass = mono_object_class (ref);
9766
9767         if (is_sre_array (klass)) {
9768                 MonoType *res;
9769                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9770                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9771                 g_assert (base);
9772                 if (sre_array->rank == 0) //single dimentional array
9773                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9774                 else
9775                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9776                 sre_array->type.type = res;
9777                 return res;
9778         } else if (is_sre_byref (klass)) {
9779                 MonoType *res;
9780                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9781                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9782                 g_assert (base);
9783                 res = &mono_class_from_mono_type (base)->this_arg;
9784                 sre_byref->type.type = res;
9785                 return res;
9786         } else if (is_sre_pointer (klass)) {
9787                 MonoType *res;
9788                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9789                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9790                 g_assert (base);
9791                 res = &mono_ptr_class_get (base)->byval_arg;
9792                 sre_pointer->type.type = res;
9793                 return res;
9794         } else if (is_sre_generic_instance (klass)) {
9795                 MonoType *res, **types;
9796                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9797                 int i, count;
9798
9799                 count = mono_array_length (gclass->type_arguments);
9800                 types = g_new0 (MonoType*, count);
9801                 for (i = 0; i < count; ++i) {
9802                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9803                         types [i] = mono_reflection_type_get_handle (t);
9804                         if (!types[i]) {
9805                                 g_free (types);
9806                                 return NULL;
9807                         }
9808                 }
9809
9810                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9811                 g_free (types);
9812                 g_assert (res);
9813                 gclass->type.type = res;
9814                 return res;
9815         }
9816
9817         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9818         return NULL;
9819 }
9820
9821
9822
9823 void
9824 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9825 {
9826         mono_reflection_type_get_handle (type);
9827 }
9828
9829 void
9830 mono_reflection_register_with_runtime (MonoReflectionType *type)
9831 {
9832         MonoType *res = mono_reflection_type_get_handle (type);
9833         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9834         MonoClass *klass;
9835
9836         if (!res)
9837                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9838
9839         klass = mono_class_from_mono_type (res);
9840
9841         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9842         mono_domain_lock (domain);
9843
9844         if (!image_is_dynamic (klass->image)) {
9845                 mono_class_setup_supertypes (klass);
9846         } else {
9847                 if (!domain->type_hash)
9848                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9849                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9850                 mono_g_hash_table_insert (domain->type_hash, res, type);
9851         }
9852         mono_domain_unlock (domain);
9853         mono_loader_unlock ();
9854 }
9855
9856 /**
9857  * LOCKING: Assumes the loader lock is held.
9858  */
9859 static MonoMethodSignature*
9860 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9861         MonoMethodSignature *sig;
9862         int count, i;
9863
9864         count = parameters? mono_array_length (parameters): 0;
9865
9866         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9867         sig->param_count = count;
9868         sig->sentinelpos = -1; /* FIXME */
9869         for (i = 0; i < count; ++i)
9870                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9871         return sig;
9872 }
9873
9874 /**
9875  * LOCKING: Assumes the loader lock is held.
9876  */
9877 static MonoMethodSignature*
9878 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9879         MonoMethodSignature *sig;
9880
9881         sig = parameters_to_signature (image, ctor->parameters);
9882         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9883         sig->ret = &mono_defaults.void_class->byval_arg;
9884         return sig;
9885 }
9886
9887 /**
9888  * LOCKING: Assumes the loader lock is held.
9889  */
9890 static MonoMethodSignature*
9891 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9892         MonoMethodSignature *sig;
9893
9894         sig = parameters_to_signature (image, method->parameters);
9895         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9896         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9897         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9898         return sig;
9899 }
9900
9901 static MonoMethodSignature*
9902 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9903         MonoMethodSignature *sig;
9904
9905         sig = parameters_to_signature (NULL, method->parameters);
9906         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9907         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9908         sig->generic_param_count = 0;
9909         return sig;
9910 }
9911
9912 static void
9913 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9914 {
9915         MonoClass *klass = mono_object_class (prop);
9916         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9917                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9918                 *name = mono_string_to_utf8 (pb->name);
9919                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9920         } else {
9921                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9922                 *name = g_strdup (p->property->name);
9923                 if (p->property->get)
9924                         *type = mono_method_signature (p->property->get)->ret;
9925                 else
9926                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9927         }
9928 }
9929
9930 static void
9931 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9932 {
9933         MonoClass *klass = mono_object_class (field);
9934         if (strcmp (klass->name, "FieldBuilder") == 0) {
9935                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9936                 *name = mono_string_to_utf8 (fb->name);
9937                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9938         } else {
9939                 MonoReflectionField *f = (MonoReflectionField *)field;
9940                 *name = g_strdup (mono_field_get_name (f->field));
9941                 *type = f->field->type;
9942         }
9943 }
9944
9945 #else /* DISABLE_REFLECTION_EMIT */
9946
9947 void
9948 mono_reflection_register_with_runtime (MonoReflectionType *type)
9949 {
9950         /* This is empty */
9951 }
9952
9953 static gboolean
9954 is_sre_type_builder (MonoClass *klass)
9955 {
9956         return FALSE;
9957 }
9958
9959 static gboolean
9960 is_sre_generic_instance (MonoClass *klass)
9961 {
9962         return FALSE;
9963 }
9964
9965 static void
9966 init_type_builder_generics (MonoObject *type)
9967 {
9968 }
9969
9970 #endif /* !DISABLE_REFLECTION_EMIT */
9971
9972
9973 static gboolean
9974 is_sr_mono_field (MonoClass *klass)
9975 {
9976         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9977 }
9978
9979 static gboolean
9980 is_sr_mono_property (MonoClass *klass)
9981 {
9982         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9983 }
9984
9985 static gboolean
9986 is_sr_mono_method (MonoClass *klass)
9987 {
9988         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9989 }
9990
9991 static gboolean
9992 is_sr_mono_cmethod (MonoClass *klass)
9993 {
9994         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9995 }
9996
9997 static gboolean
9998 is_sr_mono_generic_method (MonoClass *klass)
9999 {
10000         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10001 }
10002
10003 static gboolean
10004 is_sr_mono_generic_cmethod (MonoClass *klass)
10005 {
10006         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10007 }
10008
10009 gboolean
10010 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10011 {
10012         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10013 }
10014
10015 static gboolean
10016 is_usertype (MonoReflectionType *ref)
10017 {
10018         MonoClass *klass = mono_object_class (ref);
10019         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10020 }
10021
10022 static MonoReflectionType*
10023 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10024 {
10025         mono_error_init (error);
10026         if (!type || type->type)
10027                 return type;
10028
10029         if (is_usertype (type)) {
10030                 type = mono_reflection_type_get_underlying_system_type (type);
10031                 if (is_usertype (type)) {
10032                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10033                         return NULL;
10034                 }
10035         }
10036
10037         return type;
10038 }
10039 /*
10040  * Encode a value in a custom attribute stream of bytes.
10041  * The value to encode is either supplied as an object in argument val
10042  * (valuetypes are boxed), or as a pointer to the data in the
10043  * argument argval.
10044  * @type represents the type of the value
10045  * @buffer is the start of the buffer
10046  * @p the current position in the buffer
10047  * @buflen contains the size of the buffer and is used to return the new buffer size
10048  * if this needs to be realloced.
10049  * @retbuffer and @retp return the start and the position of the buffer
10050  */
10051 static void
10052 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10053 {
10054         MonoTypeEnum simple_type;
10055         
10056         if ((p-buffer) + 10 >= *buflen) {
10057                 char *newbuf;
10058                 *buflen *= 2;
10059                 newbuf = (char *)g_realloc (buffer, *buflen);
10060                 p = newbuf + (p-buffer);
10061                 buffer = newbuf;
10062         }
10063         if (!argval)
10064                 argval = ((char*)arg + sizeof (MonoObject));
10065         simple_type = type->type;
10066 handle_enum:
10067         switch (simple_type) {
10068         case MONO_TYPE_BOOLEAN:
10069         case MONO_TYPE_U1:
10070         case MONO_TYPE_I1:
10071                 *p++ = *argval;
10072                 break;
10073         case MONO_TYPE_CHAR:
10074         case MONO_TYPE_U2:
10075         case MONO_TYPE_I2:
10076                 swap_with_size (p, argval, 2, 1);
10077                 p += 2;
10078                 break;
10079         case MONO_TYPE_U4:
10080         case MONO_TYPE_I4:
10081         case MONO_TYPE_R4:
10082                 swap_with_size (p, argval, 4, 1);
10083                 p += 4;
10084                 break;
10085         case MONO_TYPE_R8:
10086                 swap_with_size (p, argval, 8, 1);
10087                 p += 8;
10088                 break;
10089         case MONO_TYPE_U8:
10090         case MONO_TYPE_I8:
10091                 swap_with_size (p, argval, 8, 1);
10092                 p += 8;
10093                 break;
10094         case MONO_TYPE_VALUETYPE:
10095                 if (type->data.klass->enumtype) {
10096                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10097                         goto handle_enum;
10098                 } else {
10099                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10100                 }
10101                 break;
10102         case MONO_TYPE_STRING: {
10103                 char *str;
10104                 guint32 slen;
10105                 if (!arg) {
10106                         *p++ = 0xFF;
10107                         break;
10108                 }
10109                 str = mono_string_to_utf8 ((MonoString*)arg);
10110                 slen = strlen (str);
10111                 if ((p-buffer) + 10 + slen >= *buflen) {
10112                         char *newbuf;
10113                         *buflen *= 2;
10114                         *buflen += slen;
10115                         newbuf = (char *)g_realloc (buffer, *buflen);
10116                         p = newbuf + (p-buffer);
10117                         buffer = newbuf;
10118                 }
10119                 mono_metadata_encode_value (slen, p, &p);
10120                 memcpy (p, str, slen);
10121                 p += slen;
10122                 g_free (str);
10123                 break;
10124         }
10125         case MONO_TYPE_CLASS: {
10126                 char *str;
10127                 guint32 slen;
10128                 if (!arg) {
10129                         *p++ = 0xFF;
10130                         break;
10131                 }
10132 handle_type:
10133                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10134                 slen = strlen (str);
10135                 if ((p-buffer) + 10 + slen >= *buflen) {
10136                         char *newbuf;
10137                         *buflen *= 2;
10138                         *buflen += slen;
10139                         newbuf = (char *)g_realloc (buffer, *buflen);
10140                         p = newbuf + (p-buffer);
10141                         buffer = newbuf;
10142                 }
10143                 mono_metadata_encode_value (slen, p, &p);
10144                 memcpy (p, str, slen);
10145                 p += slen;
10146                 g_free (str);
10147                 break;
10148         }
10149         case MONO_TYPE_SZARRAY: {
10150                 int len, i;
10151                 MonoClass *eclass, *arg_eclass;
10152
10153                 if (!arg) {
10154                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10155                         break;
10156                 }
10157                 len = mono_array_length ((MonoArray*)arg);
10158                 *p++ = len & 0xff;
10159                 *p++ = (len >> 8) & 0xff;
10160                 *p++ = (len >> 16) & 0xff;
10161                 *p++ = (len >> 24) & 0xff;
10162                 *retp = p;
10163                 *retbuffer = buffer;
10164                 eclass = type->data.klass;
10165                 arg_eclass = mono_object_class (arg)->element_class;
10166
10167                 if (!eclass) {
10168                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10169                         eclass = mono_defaults.object_class;
10170                 }
10171                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10172                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10173                         int elsize = mono_class_array_element_size (arg_eclass);
10174                         for (i = 0; i < len; ++i) {
10175                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10176                                 elptr += elsize;
10177                         }
10178                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10179                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10180                         int elsize = mono_class_array_element_size (eclass);
10181                         for (i = 0; i < len; ++i) {
10182                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10183                                 elptr += elsize;
10184                         }
10185                 } else {
10186                         for (i = 0; i < len; ++i) {
10187                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10188                         }
10189                 }
10190                 break;
10191         }
10192         case MONO_TYPE_OBJECT: {
10193                 MonoClass *klass;
10194                 char *str;
10195                 guint32 slen;
10196
10197                 /*
10198                  * The parameter type is 'object' but the type of the actual
10199                  * argument is not. So we have to add type information to the blob
10200                  * too. This is completely undocumented in the spec.
10201                  */
10202
10203                 if (arg == NULL) {
10204                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10205                         *p++ = 0xFF;
10206                         break;
10207                 }
10208                 
10209                 klass = mono_object_class (arg);
10210
10211                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10212                         *p++ = 0x50;
10213                         goto handle_type;
10214                 } else if (klass->enumtype) {
10215                         *p++ = 0x55;
10216                 } else if (klass == mono_defaults.string_class) {
10217                         simple_type = MONO_TYPE_STRING;
10218                         *p++ = 0x0E;
10219                         goto handle_enum;
10220                 } else if (klass->rank == 1) {
10221                         *p++ = 0x1D;
10222                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10223                                 /* See Partition II, Appendix B3 */
10224                                 *p++ = 0x51;
10225                         else
10226                                 *p++ = klass->element_class->byval_arg.type;
10227                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10228                         break;
10229                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10230                         *p++ = simple_type = klass->byval_arg.type;
10231                         goto handle_enum;
10232                 } else {
10233                         g_error ("unhandled type in custom attr");
10234                 }
10235                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10236                 slen = strlen (str);
10237                 if ((p-buffer) + 10 + slen >= *buflen) {
10238                         char *newbuf;
10239                         *buflen *= 2;
10240                         *buflen += slen;
10241                         newbuf = (char *)g_realloc (buffer, *buflen);
10242                         p = newbuf + (p-buffer);
10243                         buffer = newbuf;
10244                 }
10245                 mono_metadata_encode_value (slen, p, &p);
10246                 memcpy (p, str, slen);
10247                 p += slen;
10248                 g_free (str);
10249                 simple_type = mono_class_enum_basetype (klass)->type;
10250                 goto handle_enum;
10251         }
10252         default:
10253                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10254         }
10255         *retp = p;
10256         *retbuffer = buffer;
10257 }
10258
10259 static void
10260 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10261 {
10262         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10263                 char *str = type_get_qualified_name (type, NULL);
10264                 int slen = strlen (str);
10265
10266                 *p++ = 0x55;
10267                 /*
10268                  * This seems to be optional...
10269                  * *p++ = 0x80;
10270                  */
10271                 mono_metadata_encode_value (slen, p, &p);
10272                 memcpy (p, str, slen);
10273                 p += slen;
10274                 g_free (str);
10275         } else if (type->type == MONO_TYPE_OBJECT) {
10276                 *p++ = 0x51;
10277         } else if (type->type == MONO_TYPE_CLASS) {
10278                 /* it should be a type: encode_cattr_value () has the check */
10279                 *p++ = 0x50;
10280         } else {
10281                 mono_metadata_encode_value (type->type, p, &p);
10282                 if (type->type == MONO_TYPE_SZARRAY)
10283                         /* See the examples in Partition VI, Annex B */
10284                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10285         }
10286
10287         *retp = p;
10288 }
10289
10290 #ifndef DISABLE_REFLECTION_EMIT
10291 static void
10292 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10293 {
10294         int len;
10295         /* Preallocate a large enough buffer */
10296         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10297                 char *str = type_get_qualified_name (type, NULL);
10298                 len = strlen (str);
10299                 g_free (str);
10300         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10301                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10302                 len = strlen (str);
10303                 g_free (str);
10304         } else {
10305                 len = 0;
10306         }
10307         len += strlen (name);
10308
10309         if ((p-buffer) + 20 + len >= *buflen) {
10310                 char *newbuf;
10311                 *buflen *= 2;
10312                 *buflen += len;
10313                 newbuf = (char *)g_realloc (buffer, *buflen);
10314                 p = newbuf + (p-buffer);
10315                 buffer = newbuf;
10316         }
10317
10318         encode_field_or_prop_type (type, p, &p);
10319
10320         len = strlen (name);
10321         mono_metadata_encode_value (len, p, &p);
10322         memcpy (p, name, len);
10323         p += len;
10324         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10325         *retp = p;
10326         *retbuffer = buffer;
10327 }
10328
10329 /*
10330  * mono_reflection_get_custom_attrs_blob:
10331  * @ctor: custom attribute constructor
10332  * @ctorArgs: arguments o the constructor
10333  * @properties:
10334  * @propValues:
10335  * @fields:
10336  * @fieldValues:
10337  * 
10338  * Creates the blob of data that needs to be saved in the metadata and that represents
10339  * the custom attributed described by @ctor, @ctorArgs etc.
10340  * Returns: a Byte array representing the blob of data.
10341  */
10342 MonoArray*
10343 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10344 {
10345         MonoArray *result;
10346         MonoMethodSignature *sig;
10347         MonoObject *arg;
10348         char *buffer, *p;
10349         guint32 buflen, i;
10350
10351         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10352                 /* sig is freed later so allocate it in the heap */
10353                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10354         } else {
10355                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10356         }
10357
10358         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10359         buflen = 256;
10360         p = buffer = (char *)g_malloc (buflen);
10361         /* write the prolog */
10362         *p++ = 1;
10363         *p++ = 0;
10364         for (i = 0; i < sig->param_count; ++i) {
10365                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10366                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10367         }
10368         i = 0;
10369         if (properties)
10370                 i += mono_array_length (properties);
10371         if (fields)
10372                 i += mono_array_length (fields);
10373         *p++ = i & 0xff;
10374         *p++ = (i >> 8) & 0xff;
10375         if (properties) {
10376                 MonoObject *prop;
10377                 for (i = 0; i < mono_array_length (properties); ++i) {
10378                         MonoType *ptype;
10379                         char *pname;
10380
10381                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10382                         get_prop_name_and_type (prop, &pname, &ptype);
10383                         *p++ = 0x54; /* PROPERTY signature */
10384                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10385                         g_free (pname);
10386                 }
10387         }
10388
10389         if (fields) {
10390                 MonoObject *field;
10391                 for (i = 0; i < mono_array_length (fields); ++i) {
10392                         MonoType *ftype;
10393                         char *fname;
10394
10395                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10396                         get_field_name_and_type (field, &fname, &ftype);
10397                         *p++ = 0x53; /* FIELD signature */
10398                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10399                         g_free (fname);
10400                 }
10401         }
10402
10403         g_assert (p - buffer <= buflen);
10404         buflen = p - buffer;
10405         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10406         p = mono_array_addr (result, char, 0);
10407         memcpy (p, buffer, buflen);
10408         g_free (buffer);
10409         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10410                 g_free (sig);
10411         return result;
10412 }
10413
10414 /*
10415  * mono_reflection_setup_internal_class:
10416  * @tb: a TypeBuilder object
10417  *
10418  * Creates a MonoClass that represents the TypeBuilder.
10419  * This is a trick that lets us simplify a lot of reflection code
10420  * (and will allow us to support Build and Run assemblies easier).
10421  */
10422 void
10423 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10424 {
10425         MonoError error;
10426         MonoClass *klass, *parent;
10427
10428         RESOLVE_TYPE (tb->parent, &error);
10429         mono_error_raise_exception (&error); /* FIXME don't raise here */
10430
10431         mono_loader_lock ();
10432
10433         if (tb->parent) {
10434                 /* check so we can compile corlib correctly */
10435                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10436                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10437                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10438                 } else {
10439                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10440                 }
10441         } else {
10442                 parent = NULL;
10443         }
10444         
10445         /* the type has already being created: it means we just have to change the parent */
10446         if (tb->type.type) {
10447                 klass = mono_class_from_mono_type (tb->type.type);
10448                 klass->parent = NULL;
10449                 /* fool mono_class_setup_parent */
10450                 klass->supertypes = NULL;
10451                 mono_class_setup_parent (klass, parent);
10452                 mono_class_setup_mono_type (klass);
10453                 mono_loader_unlock ();
10454                 return;
10455         }
10456
10457         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10458
10459         klass->image = &tb->module->dynamic_image->image;
10460
10461         klass->inited = 1; /* we lie to the runtime */
10462         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10463         if (!mono_error_ok (&error))
10464                 goto failure;
10465         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10466         if (!mono_error_ok (&error))
10467                 goto failure;
10468         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10469         klass->flags = tb->attrs;
10470         
10471         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10472
10473         klass->element_class = klass;
10474
10475         if (mono_class_get_ref_info (klass) == NULL) {
10476
10477                 mono_class_set_ref_info (klass, tb);
10478
10479                 /* Put into cache so mono_class_get_checked () will find it.
10480                 Skip nested types as those should not be available on the global scope. */
10481                 if (!tb->nesting_type)
10482                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10483
10484                 /*
10485                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10486                 by performing a mono_class_get which does the full resolution.
10487
10488                 Working around this semantics would require us to write a lot of code for no clear advantage.
10489                 */
10490                 mono_image_append_class_to_reflection_info_set (klass);
10491         } else {
10492                 g_assert (mono_class_get_ref_info (klass) == tb);
10493         }
10494
10495         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10496
10497         if (parent != NULL) {
10498                 mono_class_setup_parent (klass, parent);
10499         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10500                 const char *old_n = klass->name;
10501                 /* trick to get relative numbering right when compiling corlib */
10502                 klass->name = "BuildingObject";
10503                 mono_class_setup_parent (klass, mono_defaults.object_class);
10504                 klass->name = old_n;
10505         }
10506
10507         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10508                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10509                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10510                 klass->instance_size = sizeof (MonoObject);
10511                 klass->size_inited = 1;
10512                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10513         }
10514
10515         mono_class_setup_mono_type (klass);
10516
10517         mono_class_setup_supertypes (klass);
10518
10519         /*
10520          * FIXME: handle interfaces.
10521          */
10522
10523         tb->type.type = &klass->byval_arg;
10524
10525         if (tb->nesting_type) {
10526                 g_assert (tb->nesting_type->type);
10527                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10528         }
10529
10530         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10531
10532         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10533         
10534         mono_loader_unlock ();
10535         return;
10536
10537 failure:
10538         mono_loader_unlock ();
10539         mono_error_raise_exception (&error);
10540 }
10541
10542 /*
10543  * mono_reflection_setup_generic_class:
10544  * @tb: a TypeBuilder object
10545  *
10546  * Setup the generic class before adding the first generic parameter.
10547  */
10548 void
10549 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10550 {
10551 }
10552
10553 /*
10554  * mono_reflection_create_generic_class:
10555  * @tb: a TypeBuilder object
10556  *
10557  * Creates the generic class after all generic parameters have been added.
10558  */
10559 void
10560 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10561 {
10562         MonoClass *klass;
10563         int count, i;
10564
10565         klass = mono_class_from_mono_type (tb->type.type);
10566
10567         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10568
10569         if (klass->generic_container || (count == 0))
10570                 return;
10571
10572         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10573
10574         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10575
10576         klass->generic_container->owner.klass = klass;
10577         klass->generic_container->type_argc = count;
10578         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10579
10580         klass->is_generic = 1;
10581
10582         for (i = 0; i < count; i++) {
10583                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10584                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10585                 klass->generic_container->type_params [i] = *param;
10586                 /*Make sure we are a diferent type instance */
10587                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10588                 klass->generic_container->type_params [i].info.pklass = NULL;
10589                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10590
10591                 g_assert (klass->generic_container->type_params [i].param.owner);
10592         }
10593
10594         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10595 }
10596
10597 /*
10598  * mono_reflection_create_internal_class:
10599  * @tb: a TypeBuilder object
10600  *
10601  * Actually create the MonoClass that is associated with the TypeBuilder.
10602  */
10603 void
10604 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10605 {
10606         MonoClass *klass;
10607
10608         klass = mono_class_from_mono_type (tb->type.type);
10609
10610         mono_loader_lock ();
10611         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10612                 MonoReflectionFieldBuilder *fb;
10613                 MonoClass *ec;
10614                 MonoType *enum_basetype;
10615
10616                 g_assert (tb->fields != NULL);
10617                 g_assert (mono_array_length (tb->fields) >= 1);
10618
10619                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10620
10621                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10622                         mono_loader_unlock ();
10623                         return;
10624                 }
10625
10626                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10627                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10628                 if (!klass->element_class)
10629                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10630
10631                 /*
10632                  * get the element_class from the current corlib.
10633                  */
10634                 ec = default_class_from_mono_type (enum_basetype);
10635                 klass->instance_size = ec->instance_size;
10636                 klass->size_inited = 1;
10637                 /* 
10638                  * this is almost safe to do with enums and it's needed to be able
10639                  * to create objects of the enum type (for use in SetConstant).
10640                  */
10641                 /* FIXME: Does this mean enums can't have method overrides ? */
10642                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10643         }
10644         mono_loader_unlock ();
10645 }
10646
10647 static MonoMarshalSpec*
10648 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10649                                                                 MonoReflectionMarshal *minfo)
10650 {
10651         MonoMarshalSpec *res;
10652
10653         res = image_g_new0 (image, MonoMarshalSpec, 1);
10654         res->native = (MonoMarshalNative)minfo->type;
10655
10656         switch (minfo->type) {
10657         case MONO_NATIVE_LPARRAY:
10658                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10659                 if (minfo->has_size) {
10660                         res->data.array_data.param_num = minfo->param_num;
10661                         res->data.array_data.num_elem = minfo->count;
10662                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10663                 }
10664                 else {
10665                         res->data.array_data.param_num = -1;
10666                         res->data.array_data.num_elem = -1;
10667                         res->data.array_data.elem_mult = -1;
10668                 }
10669                 break;
10670
10671         case MONO_NATIVE_BYVALTSTR:
10672         case MONO_NATIVE_BYVALARRAY:
10673                 res->data.array_data.num_elem = minfo->count;
10674                 break;
10675
10676         case MONO_NATIVE_CUSTOM:
10677                 if (minfo->marshaltyperef)
10678                         res->data.custom_data.custom_name =
10679                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10680                 if (minfo->mcookie)
10681                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10682                 break;
10683
10684         default:
10685                 break;
10686         }
10687
10688         return res;
10689 }
10690 #endif /* !DISABLE_REFLECTION_EMIT */
10691
10692 MonoReflectionMarshalAsAttribute*
10693 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10694                                                                                    MonoMarshalSpec *spec)
10695 {
10696         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10697         MonoError error;
10698         MonoReflectionType *rt;
10699         MonoReflectionMarshalAsAttribute *minfo;
10700         MonoType *mtype;
10701
10702         if (!System_Reflection_Emit_MarshalAsAttribute) {
10703                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10704                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10705                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10706         }
10707
10708         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10709         minfo->utype = spec->native;
10710
10711         switch (minfo->utype) {
10712         case MONO_NATIVE_LPARRAY:
10713                 minfo->array_subtype = spec->data.array_data.elem_type;
10714                 minfo->size_const = spec->data.array_data.num_elem;
10715                 if (spec->data.array_data.param_num != -1)
10716                         minfo->size_param_index = spec->data.array_data.param_num;
10717                 break;
10718
10719         case MONO_NATIVE_BYVALTSTR:
10720         case MONO_NATIVE_BYVALARRAY:
10721                 minfo->size_const = spec->data.array_data.num_elem;
10722                 break;
10723
10724         case MONO_NATIVE_CUSTOM:
10725                 if (spec->data.custom_data.custom_name) {
10726                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10727                         if (mtype) {
10728                                 rt = mono_type_get_object_checked (domain, mtype, &error);
10729                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10730
10731                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10732                         }
10733
10734                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10735                 }
10736                 if (spec->data.custom_data.cookie)
10737                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10738                 break;
10739
10740         default:
10741                 break;
10742         }
10743
10744         return minfo;
10745 }
10746
10747 #ifndef DISABLE_REFLECTION_EMIT
10748 static MonoMethod*
10749 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10750                                          ReflectionMethodBuilder *rmb,
10751                                          MonoMethodSignature *sig)
10752 {
10753         MonoError error;
10754         MonoMethod *m;
10755         MonoMethodWrapper *wrapperm;
10756         MonoMarshalSpec **specs;
10757         MonoReflectionMethodAux *method_aux;
10758         MonoImage *image;
10759         gboolean dynamic;
10760         int i;
10761
10762         mono_error_init (&error);
10763         /*
10764          * Methods created using a MethodBuilder should have their memory allocated
10765          * inside the image mempool, while dynamic methods should have their memory
10766          * malloc'd.
10767          */
10768         dynamic = rmb->refs != NULL;
10769         image = dynamic ? NULL : klass->image;
10770
10771         if (!dynamic)
10772                 g_assert (!klass->generic_class);
10773
10774         mono_loader_lock ();
10775
10776         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10777                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10778                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10779         else
10780                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10781
10782         wrapperm = (MonoMethodWrapper*)m;
10783
10784         m->dynamic = dynamic;
10785         m->slot = -1;
10786         m->flags = rmb->attrs;
10787         m->iflags = rmb->iattrs;
10788         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10789         m->klass = klass;
10790         m->signature = sig;
10791         m->sre_method = TRUE;
10792         m->skip_visibility = rmb->skip_visibility;
10793         if (rmb->table_idx)
10794                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10795
10796         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10797                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10798                         m->string_ctor = 1;
10799
10800                 m->signature->pinvoke = 1;
10801         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10802                 m->signature->pinvoke = 1;
10803
10804                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10805
10806                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10807                 g_assert (mono_error_ok (&error));
10808                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10809                 g_assert (mono_error_ok (&error));
10810                 
10811                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10812
10813                 if (image_is_dynamic (klass->image))
10814                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10815
10816                 mono_loader_unlock ();
10817
10818                 return m;
10819         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10820                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10821                 MonoMethodHeader *header;
10822                 guint32 code_size;
10823                 gint32 max_stack, i;
10824                 gint32 num_locals = 0;
10825                 gint32 num_clauses = 0;
10826                 guint8 *code;
10827
10828                 if (rmb->ilgen) {
10829                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10830                         code_size = rmb->ilgen->code_len;
10831                         max_stack = rmb->ilgen->max_stack;
10832                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10833                         if (rmb->ilgen->ex_handlers)
10834                                 num_clauses = method_count_clauses (rmb->ilgen);
10835                 } else {
10836                         if (rmb->code) {
10837                                 code = mono_array_addr (rmb->code, guint8, 0);
10838                                 code_size = mono_array_length (rmb->code);
10839                                 /* we probably need to run a verifier on the code... */
10840                                 max_stack = 8; 
10841                         }
10842                         else {
10843                                 code = NULL;
10844                                 code_size = 0;
10845                                 max_stack = 8;
10846                         }
10847                 }
10848
10849                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10850                 header->code_size = code_size;
10851                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10852                 memcpy ((char*)header->code, code, code_size);
10853                 header->max_stack = max_stack;
10854                 header->init_locals = rmb->init_locals;
10855                 header->num_locals = num_locals;
10856
10857                 for (i = 0; i < num_locals; ++i) {
10858                         MonoReflectionLocalBuilder *lb = 
10859                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10860
10861                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10862                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10863                 }
10864
10865                 header->num_clauses = num_clauses;
10866                 if (num_clauses) {
10867                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10868                                  rmb->ilgen, num_clauses);
10869                 }
10870
10871                 wrapperm->header = header;
10872         }
10873
10874         if (rmb->generic_params) {
10875                 int count = mono_array_length (rmb->generic_params);
10876                 MonoGenericContainer *container = rmb->generic_container;
10877
10878                 g_assert (container);
10879
10880                 container->type_argc = count;
10881                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10882                 container->owner.method = m;
10883                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10884
10885                 m->is_generic = TRUE;
10886                 mono_method_set_generic_container (m, container);
10887
10888                 for (i = 0; i < count; i++) {
10889                         MonoReflectionGenericParam *gp =
10890                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10891                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10892                         container->type_params [i] = *param;
10893                 }
10894
10895                 /*
10896                  * The method signature might have pointers to generic parameters that belong to other methods.
10897                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10898                  * generic parameters.
10899                  */
10900                 for (i = 0; i < m->signature->param_count; ++i) {
10901                         MonoType *t = m->signature->params [i];
10902                         if (t->type == MONO_TYPE_MVAR) {
10903                                 MonoGenericParam *gparam =  t->data.generic_param;
10904                                 if (gparam->num < count) {
10905                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10906                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10907                                 }
10908
10909                         }
10910                 }
10911
10912                 if (klass->generic_container) {
10913                         container->parent = klass->generic_container;
10914                         container->context.class_inst = klass->generic_container->context.class_inst;
10915                 }
10916                 container->context.method_inst = mono_get_shared_generic_inst (container);
10917         }
10918
10919         if (rmb->refs) {
10920                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10921                 int i;
10922                 void **data;
10923
10924                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10925
10926                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10927                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10928                 for (i = 0; i < rmb->nrefs; ++i)
10929                         data [i + 1] = rmb->refs [i];
10930         }
10931
10932         method_aux = NULL;
10933
10934         /* Parameter info */
10935         if (rmb->pinfo) {
10936                 if (!method_aux)
10937                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10938                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10939                 for (i = 0; i <= m->signature->param_count; ++i) {
10940                         MonoReflectionParamBuilder *pb;
10941                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10942                                 if ((i > 0) && (pb->attrs)) {
10943                                         /* Make a copy since it might point to a shared type structure */
10944                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10945                                         m->signature->params [i - 1]->attrs = pb->attrs;
10946                                 }
10947
10948                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10949                                         MonoDynamicImage *assembly;
10950                                         guint32 idx, len;
10951                                         MonoTypeEnum def_type;
10952                                         char *p;
10953                                         const char *p2;
10954
10955                                         if (!method_aux->param_defaults) {
10956                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10957                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10958                                         }
10959                                         assembly = (MonoDynamicImage*)klass->image;
10960                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10961                                         /* Copy the data from the blob since it might get realloc-ed */
10962                                         p = assembly->blob.data + idx;
10963                                         len = mono_metadata_decode_blob_size (p, &p2);
10964                                         len += p2 - p;
10965                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10966                                         method_aux->param_default_types [i] = def_type;
10967                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10968                                 }
10969
10970                                 if (pb->name) {
10971                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10972                                         g_assert (mono_error_ok (&error));
10973                                 }
10974                                 if (pb->cattrs) {
10975                                         if (!method_aux->param_cattr)
10976                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10977                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10978                                 }
10979                         }
10980                 }
10981         }
10982
10983         /* Parameter marshalling */
10984         specs = NULL;
10985         if (rmb->pinfo)         
10986                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10987                         MonoReflectionParamBuilder *pb;
10988                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10989                                 if (pb->marshal_info) {
10990                                         if (specs == NULL)
10991                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10992                                         specs [pb->position] = 
10993                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10994                                 }
10995                         }
10996                 }
10997         if (specs != NULL) {
10998                 if (!method_aux)
10999                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11000                 method_aux->param_marshall = specs;
11001         }
11002
11003         if (image_is_dynamic (klass->image) && method_aux)
11004                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11005
11006         mono_loader_unlock ();
11007
11008         return m;
11009 }       
11010
11011 static MonoMethod*
11012 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
11013 {
11014         ReflectionMethodBuilder rmb;
11015         MonoMethodSignature *sig;
11016
11017         mono_loader_lock ();
11018         sig = ctor_builder_to_signature (klass->image, mb);
11019         mono_loader_unlock ();
11020
11021         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
11022
11023         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11024         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11025
11026         /* If we are in a generic class, we might be called multiple times from inflate_method */
11027         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11028                 /* ilgen is no longer needed */
11029                 mb->ilgen = NULL;
11030         }
11031
11032         return mb->mhandle;
11033 }
11034
11035 static MonoMethod*
11036 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11037 {
11038         ReflectionMethodBuilder rmb;
11039         MonoMethodSignature *sig;
11040
11041         mono_loader_lock ();
11042         sig = method_builder_to_signature (klass->image, mb);
11043         mono_loader_unlock ();
11044
11045         reflection_methodbuilder_from_method_builder (&rmb, mb);
11046
11047         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11048         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11049
11050         /* If we are in a generic class, we might be called multiple times from inflate_method */
11051         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11052                 /* ilgen is no longer needed */
11053                 mb->ilgen = NULL;
11054         }
11055         return mb->mhandle;
11056 }
11057
11058 static MonoClassField*
11059 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11060 {
11061         MonoClassField *field;
11062         MonoType *custom;
11063         MonoError error;
11064
11065         field = g_new0 (MonoClassField, 1);
11066
11067         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11068         g_assert (mono_error_ok (&error));
11069         if (fb->attrs || fb->modreq || fb->modopt) {
11070                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11071                 field->type->attrs = fb->attrs;
11072
11073                 g_assert (image_is_dynamic (klass->image));
11074                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11075                 g_free (field->type);
11076                 field->type = mono_metadata_type_dup (klass->image, custom);
11077                 g_free (custom);
11078         } else {
11079                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11080         }
11081         if (fb->offset != -1)
11082                 field->offset = fb->offset;
11083         field->parent = klass;
11084         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11085
11086         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11087
11088         return field;
11089 }
11090 #endif
11091
11092 MonoType*
11093 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11094 {
11095         MonoClass *klass;
11096         MonoReflectionTypeBuilder *tb = NULL;
11097         gboolean is_dynamic = FALSE;
11098         MonoClass *geninst;
11099
11100         mono_loader_lock ();
11101
11102         if (is_sre_type_builder (mono_object_class (type))) {
11103                 tb = (MonoReflectionTypeBuilder *) type;
11104
11105                 is_dynamic = TRUE;
11106         } else if (is_sre_generic_instance (mono_object_class (type))) {
11107                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11108                 MonoReflectionType *gtd = rgi->generic_type;
11109
11110                 if (is_sre_type_builder (mono_object_class (gtd))) {
11111                         tb = (MonoReflectionTypeBuilder *)gtd;
11112                         is_dynamic = TRUE;
11113                 }
11114         }
11115
11116         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11117         if (tb && tb->generic_container)
11118                 mono_reflection_create_generic_class (tb);
11119
11120         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11121         if (!klass->generic_container) {
11122                 mono_loader_unlock ();
11123                 return NULL;
11124         }
11125
11126         if (klass->wastypebuilder) {
11127                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11128
11129                 is_dynamic = TRUE;
11130         }
11131
11132         mono_loader_unlock ();
11133
11134         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11135
11136         return &geninst->byval_arg;
11137 }
11138
11139 MonoClass*
11140 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11141 {
11142         MonoGenericClass *gclass;
11143         MonoGenericInst *inst;
11144
11145         g_assert (klass->generic_container);
11146
11147         inst = mono_metadata_get_generic_inst (type_argc, types);
11148         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11149
11150         return mono_generic_class_get_class (gclass);
11151 }
11152
11153 MonoReflectionMethod*
11154 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11155 {
11156         MonoError error;
11157         MonoClass *klass;
11158         MonoMethod *method, *inflated;
11159         MonoMethodInflated *imethod;
11160         MonoGenericContext tmp_context;
11161         MonoGenericInst *ginst;
11162         MonoType **type_argv;
11163         int count, i;
11164
11165         /*FIXME but this no longer should happen*/
11166         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11167 #ifndef DISABLE_REFLECTION_EMIT
11168                 MonoReflectionMethodBuilder *mb = NULL;
11169                 MonoReflectionTypeBuilder *tb;
11170                 MonoClass *klass;
11171
11172                 mb = (MonoReflectionMethodBuilder *) rmethod;
11173                 tb = (MonoReflectionTypeBuilder *) mb->type;
11174                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11175
11176                 method = methodbuilder_to_mono_method (klass, mb);
11177 #else
11178                 g_assert_not_reached ();
11179                 method = NULL;
11180 #endif
11181         } else {
11182                 method = rmethod->method;
11183         }
11184
11185         klass = method->klass;
11186
11187         if (method->is_inflated)
11188                 method = ((MonoMethodInflated *) method)->declaring;
11189
11190         count = mono_method_signature (method)->generic_param_count;
11191         if (count != mono_array_length (types))
11192                 return NULL;
11193
11194         type_argv = g_new0 (MonoType *, count);
11195         for (i = 0; i < count; i++) {
11196                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11197                 type_argv [i] = mono_reflection_type_get_handle (garg);
11198         }
11199         ginst = mono_metadata_get_generic_inst (count, type_argv);
11200         g_free (type_argv);
11201
11202         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11203         tmp_context.method_inst = ginst;
11204
11205         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11206         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11207         imethod = (MonoMethodInflated *) inflated;
11208
11209         /*FIXME but I think this is no longer necessary*/
11210         if (image_is_dynamic (method->klass->image)) {
11211                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11212                 /*
11213                  * This table maps metadata structures representing inflated methods/fields
11214                  * to the reflection objects representing their generic definitions.
11215                  */
11216                 mono_image_lock ((MonoImage*)image);
11217                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11218                 mono_image_unlock ((MonoImage*)image);
11219         }
11220
11221         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11222                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11223         
11224         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11225 }
11226
11227 #ifndef DISABLE_REFLECTION_EMIT
11228
11229 static MonoMethod *
11230 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11231 {
11232         MonoMethodInflated *imethod;
11233         MonoGenericContext *context;
11234         int i;
11235
11236         /*
11237          * With generic code sharing the klass might not be inflated.
11238          * This can happen because classes inflated with their own
11239          * type arguments are "normalized" to the uninflated class.
11240          */
11241         if (!klass->generic_class)
11242                 return method;
11243
11244         context = mono_class_get_context (klass);
11245
11246         if (klass->method.count && klass->methods) {
11247                 /* Find the already created inflated method */
11248                 for (i = 0; i < klass->method.count; ++i) {
11249                         g_assert (klass->methods [i]->is_inflated);
11250                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11251                                 break;
11252                 }
11253                 g_assert (i < klass->method.count);
11254                 imethod = (MonoMethodInflated*)klass->methods [i];
11255         } else {
11256                 MonoError error;
11257                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11258                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11259         }
11260
11261         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11262                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11263
11264                 mono_image_lock ((MonoImage*)image);
11265                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11266                 mono_image_unlock ((MonoImage*)image);
11267         }
11268         return (MonoMethod *) imethod;
11269 }
11270
11271 static MonoMethod *
11272 inflate_method (MonoReflectionType *type, MonoObject *obj)
11273 {
11274         MonoMethod *method;
11275         MonoClass *gklass;
11276
11277         MonoClass *type_class = mono_object_class (type);
11278
11279         if (is_sre_generic_instance (type_class)) {
11280                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11281                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11282         } else if (is_sre_type_builder (type_class)) {
11283                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11284         } else if (type->type) {
11285                 gklass = mono_class_from_mono_type (type->type);
11286                 gklass = mono_class_get_generic_type_definition (gklass);
11287         } else {
11288                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11289         }
11290
11291         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11292                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11293                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11294                 else
11295                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11296         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11297                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11298         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11299                 method = ((MonoReflectionMethod *) obj)->method;
11300         else {
11301                 method = NULL; /* prevent compiler warning */
11302                 g_error ("can't handle type %s", obj->vtable->klass->name);
11303         }
11304
11305         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11306 }
11307
11308 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11309 void
11310 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11311 {
11312         MonoGenericClass *gclass;
11313         MonoDynamicGenericClass *dgclass;
11314         MonoClass *klass, *gklass;
11315         MonoType *gtype;
11316         int i;
11317
11318         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11319         klass = mono_class_from_mono_type (gtype);
11320         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11321         gclass = gtype->data.generic_class;
11322
11323         if (!gclass->is_dynamic)
11324                 return;
11325
11326         dgclass = (MonoDynamicGenericClass *) gclass;
11327
11328         if (dgclass->initialized)
11329                 return;
11330
11331         gklass = gclass->container_class;
11332         mono_class_init (gklass);
11333
11334         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11335
11336         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11337         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11338         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11339
11340         for (i = 0; i < dgclass->count_fields; i++) {
11341                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11342                 MonoClassField *field, *inflated_field = NULL;
11343
11344                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11345                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11346                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11347                         field = ((MonoReflectionField *) obj)->field;
11348                 else {
11349                         field = NULL; /* prevent compiler warning */
11350                         g_assert_not_reached ();
11351                 }
11352
11353                 dgclass->fields [i] = *field;
11354                 dgclass->fields [i].parent = klass;
11355                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11356                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11357                 dgclass->field_generic_types [i] = field->type;
11358                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11359                 dgclass->field_objects [i] = obj;
11360
11361                 if (inflated_field) {
11362                         g_free (inflated_field);
11363                 } else {
11364                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11365                 }
11366         }
11367
11368         dgclass->initialized = TRUE;
11369 }
11370
11371 void
11372 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11373 {
11374         MonoDynamicGenericClass *dgclass;
11375         int i;
11376
11377         g_assert (gclass->is_dynamic);
11378
11379         dgclass = (MonoDynamicGenericClass *)gclass;
11380
11381         for (i = 0; i < dgclass->count_fields; ++i) {
11382                 MonoClassField *field = dgclass->fields + i;
11383                 mono_metadata_free_type (field->type);
11384                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11385         }
11386 }
11387
11388 static void
11389 fix_partial_generic_class (MonoClass *klass)
11390 {
11391         MonoClass *gklass = klass->generic_class->container_class;
11392         MonoDynamicGenericClass *dgclass;
11393         int i;
11394
11395         if (klass->wastypebuilder)
11396                 return;
11397
11398         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11399         if (klass->parent != gklass->parent) {
11400                 MonoError error;
11401                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11402                 if (mono_error_ok (&error)) {
11403                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11404                         mono_metadata_free_type (parent_type);
11405                         if (parent != klass->parent) {
11406                                 /*fool mono_class_setup_parent*/
11407                                 klass->supertypes = NULL;
11408                                 mono_class_setup_parent (klass, parent);
11409                         }
11410                 } else {
11411                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11412                         mono_error_cleanup (&error);
11413                         if (gklass->wastypebuilder)
11414                                 klass->wastypebuilder = TRUE;
11415                         return;
11416                 }
11417         }
11418
11419         if (!dgclass->initialized)
11420                 return;
11421
11422         if (klass->method.count != gklass->method.count) {
11423                 klass->method.count = gklass->method.count;
11424                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11425
11426                 for (i = 0; i < klass->method.count; i++) {
11427                         MonoError error;
11428                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11429                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11430                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11431                 }
11432         }
11433
11434         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11435                 klass->interface_count = gklass->interface_count;
11436                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11437                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11438
11439                 for (i = 0; i < gklass->interface_count; ++i) {
11440                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11441                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11442                         mono_metadata_free_type (iface_type);
11443
11444                         ensure_runtime_vtable (klass->interfaces [i]);
11445                 }
11446                 klass->interfaces_inited = 1;
11447         }
11448
11449         if (klass->field.count != gklass->field.count) {
11450                 klass->field.count = gklass->field.count;
11451                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11452
11453                 for (i = 0; i < klass->field.count; i++) {
11454                         klass->fields [i] = gklass->fields [i];
11455                         klass->fields [i].parent = klass;
11456                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11457                 }
11458         }
11459
11460         /*We can only finish with this klass once it's parent has as well*/
11461         if (gklass->wastypebuilder)
11462                 klass->wastypebuilder = TRUE;
11463         return;
11464 }
11465
11466 static void
11467 ensure_generic_class_runtime_vtable (MonoClass *klass)
11468 {
11469         MonoClass *gklass = klass->generic_class->container_class;
11470
11471         ensure_runtime_vtable (gklass); 
11472
11473         fix_partial_generic_class (klass);
11474 }
11475
11476 static void
11477 ensure_runtime_vtable (MonoClass *klass)
11478 {
11479         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11480         int i, num, j;
11481
11482         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11483                 return;
11484         if (klass->parent)
11485                 ensure_runtime_vtable (klass->parent);
11486
11487         if (tb) {
11488                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11489                 num += tb->num_methods;
11490                 klass->method.count = num;
11491                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11492                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11493                 for (i = 0; i < num; ++i)
11494                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11495                 num = tb->num_methods;
11496                 j = i;
11497                 for (i = 0; i < num; ++i)
11498                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11499         
11500                 if (tb->interfaces) {
11501                         klass->interface_count = mono_array_length (tb->interfaces);
11502                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11503                         for (i = 0; i < klass->interface_count; ++i) {
11504                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11505                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11506                                 ensure_runtime_vtable (klass->interfaces [i]);
11507                         }
11508                         klass->interfaces_inited = 1;
11509                 }
11510         } else if (klass->generic_class){
11511                 ensure_generic_class_runtime_vtable (klass);
11512         }
11513
11514         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11515                 int slot_num = 0;
11516                 for (i = 0; i < klass->method.count; ++i) {
11517                         MonoMethod *im = klass->methods [i];
11518                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11519                                 im->slot = slot_num++;
11520                 }
11521                 
11522                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11523                 mono_class_setup_interface_offsets (klass);
11524                 mono_class_setup_interface_id (klass);
11525         }
11526
11527         /*
11528          * The generic vtable is needed even if image->run is not set since some
11529          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11530          * method->slot being defined.
11531          */
11532
11533         /* 
11534          * tb->methods could not be freed since it is used for determining 
11535          * overrides during dynamic vtable construction.
11536          */
11537 }
11538
11539 static MonoMethod*
11540 mono_reflection_method_get_handle (MonoObject *method)
11541 {
11542         MonoClass *klass = mono_object_class (method);
11543         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11544                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11545                 return sr_method->method;
11546         }
11547         if (is_sre_method_builder (klass)) {
11548                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11549                 return mb->mhandle;
11550         }
11551         if (is_sre_method_on_tb_inst (klass)) {
11552                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11553                 MonoMethod *result;
11554                 /*FIXME move this to a proper method and unify with resolve_object*/
11555                 if (m->method_args) {
11556                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11557                 } else {
11558                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11559                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11560                         MonoMethod *mono_method;
11561
11562                         if (is_sre_method_builder (mono_object_class (m->mb)))
11563                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11564                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11565                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11566                         else
11567                                 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)));
11568
11569                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11570                 }
11571                 return result;
11572         }
11573
11574         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11575         return NULL;
11576 }
11577
11578 void
11579 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11580 {
11581         MonoReflectionTypeBuilder *tb;
11582         int i, j, onum;
11583         MonoReflectionMethod *m;
11584
11585         *overrides = NULL;
11586         *num_overrides = 0;
11587
11588         g_assert (image_is_dynamic (klass->image));
11589
11590         if (!mono_class_get_ref_info (klass))
11591                 return;
11592
11593         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11594
11595         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11596
11597         onum = 0;
11598         if (tb->methods) {
11599                 for (i = 0; i < tb->num_methods; ++i) {
11600                         MonoReflectionMethodBuilder *mb = 
11601                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11602                         if (mb->override_methods)
11603                                 onum += mono_array_length (mb->override_methods);
11604                 }
11605         }
11606
11607         if (onum) {
11608                 *overrides = g_new0 (MonoMethod*, onum * 2);
11609
11610                 onum = 0;
11611                 for (i = 0; i < tb->num_methods; ++i) {
11612                         MonoReflectionMethodBuilder *mb = 
11613                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11614                         if (mb->override_methods) {
11615                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11616                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11617
11618                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11619                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11620
11621                                         g_assert (mb->mhandle);
11622
11623                                         onum ++;
11624                                 }
11625                         }
11626                 }
11627         }
11628
11629         *num_overrides = onum;
11630 }
11631
11632 static void
11633 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11634 {
11635         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11636         MonoReflectionFieldBuilder *fb;
11637         MonoClassField *field;
11638         MonoImage *image = klass->image;
11639         const char *p, *p2;
11640         int i;
11641         guint32 len, idx, real_size = 0;
11642
11643         klass->field.count = tb->num_fields;
11644         klass->field.first = 0;
11645
11646         mono_error_init (error);
11647
11648         if (tb->class_size) {
11649                 if ((tb->packing_size & 0xffffff00) != 0) {
11650                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11651                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11652                         return;
11653                 }
11654                 klass->packing_size = tb->packing_size;
11655                 real_size = klass->instance_size + tb->class_size;
11656         }
11657
11658         if (!klass->field.count) {
11659                 klass->instance_size = MAX (klass->instance_size, real_size);
11660                 return;
11661         }
11662         
11663         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11664         mono_class_alloc_ext (klass);
11665         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11666         /*
11667         This is, guess what, a hack.
11668         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11669         On the static path no field class is resolved, only types are built. This is the right thing to do
11670         but we suck.
11671         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11672         */
11673         klass->size_inited = 1;
11674
11675         for (i = 0; i < klass->field.count; ++i) {
11676                 MonoArray *rva_data;
11677                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11678                 field = &klass->fields [i];
11679                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11680                 if (!mono_error_ok (error))
11681                         return;
11682                 if (fb->attrs) {
11683                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11684                         field->type->attrs = fb->attrs;
11685                 } else {
11686                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11687                 }
11688
11689                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11690                         char *base = mono_array_addr (rva_data, char, 0);
11691                         size_t size = mono_array_length (rva_data);
11692                         char *data = (char *)mono_image_alloc (klass->image, size);
11693                         memcpy (data, base, size);
11694                         klass->ext->field_def_values [i].data = data;
11695                 }
11696                 if (fb->offset != -1)
11697                         field->offset = fb->offset;
11698                 field->parent = klass;
11699                 fb->handle = field;
11700                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11701
11702                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11703                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11704                 }
11705                 if (fb->def_value) {
11706                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11707                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11708                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11709                         /* Copy the data from the blob since it might get realloc-ed */
11710                         p = assembly->blob.data + idx;
11711                         len = mono_metadata_decode_blob_size (p, &p2);
11712                         len += p2 - p;
11713                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11714                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11715                 }
11716         }
11717
11718         klass->instance_size = MAX (klass->instance_size, real_size);
11719         mono_class_layout_fields (klass);
11720 }
11721
11722 static void
11723 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11724 {
11725         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11726         MonoReflectionPropertyBuilder *pb;
11727         MonoImage *image = klass->image;
11728         MonoProperty *properties;
11729         int i;
11730
11731         mono_error_init (error);
11732
11733         if (!klass->ext)
11734                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11735
11736         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11737         klass->ext->property.first = 0;
11738
11739         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11740         klass->ext->properties = properties;
11741         for (i = 0; i < klass->ext->property.count; ++i) {
11742                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11743                 properties [i].parent = klass;
11744                 properties [i].attrs = pb->attrs;
11745                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11746                 if (!mono_error_ok (error))
11747                         return;
11748                 if (pb->get_method)
11749                         properties [i].get = pb->get_method->mhandle;
11750                 if (pb->set_method)
11751                         properties [i].set = pb->set_method->mhandle;
11752
11753                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11754                 if (pb->def_value) {
11755                         guint32 len, idx;
11756                         const char *p, *p2;
11757                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11758                         if (!klass->ext->prop_def_values)
11759                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11760                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11761                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11762                         /* Copy the data from the blob since it might get realloc-ed */
11763                         p = assembly->blob.data + idx;
11764                         len = mono_metadata_decode_blob_size (p, &p2);
11765                         len += p2 - p;
11766                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11767                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11768                 }
11769         }
11770 }
11771
11772 MonoReflectionEvent *
11773 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11774 {
11775         MonoEvent *event = g_new0 (MonoEvent, 1);
11776         MonoClass *klass;
11777
11778         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11779
11780         event->parent = klass;
11781         event->attrs = eb->attrs;
11782         event->name = mono_string_to_utf8 (eb->name);
11783         if (eb->add_method)
11784                 event->add = eb->add_method->mhandle;
11785         if (eb->remove_method)
11786                 event->remove = eb->remove_method->mhandle;
11787         if (eb->raise_method)
11788                 event->raise = eb->raise_method->mhandle;
11789
11790 #ifndef MONO_SMALL_CONFIG
11791         if (eb->other_methods) {
11792                 int j;
11793                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11794                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11795                         MonoReflectionMethodBuilder *mb = 
11796                                 mono_array_get (eb->other_methods,
11797                                                 MonoReflectionMethodBuilder*, j);
11798                         event->other [j] = mb->mhandle;
11799                 }
11800         }
11801 #endif
11802
11803         return mono_event_get_object (mono_object_domain (tb), klass, event);
11804 }
11805
11806 static void
11807 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11808 {
11809         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11810         MonoReflectionEventBuilder *eb;
11811         MonoImage *image = klass->image;
11812         MonoEvent *events;
11813         int i;
11814
11815         mono_error_init (error);
11816
11817         if (!klass->ext)
11818                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11819
11820         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11821         klass->ext->event.first = 0;
11822
11823         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11824         klass->ext->events = events;
11825         for (i = 0; i < klass->ext->event.count; ++i) {
11826                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11827                 events [i].parent = klass;
11828                 events [i].attrs = eb->attrs;
11829                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11830                 if (!mono_error_ok (error))
11831                         return;
11832                 if (eb->add_method)
11833                         events [i].add = eb->add_method->mhandle;
11834                 if (eb->remove_method)
11835                         events [i].remove = eb->remove_method->mhandle;
11836                 if (eb->raise_method)
11837                         events [i].raise = eb->raise_method->mhandle;
11838
11839 #ifndef MONO_SMALL_CONFIG
11840                 if (eb->other_methods) {
11841                         int j;
11842                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11843                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11844                                 MonoReflectionMethodBuilder *mb = 
11845                                         mono_array_get (eb->other_methods,
11846                                                                         MonoReflectionMethodBuilder*, j);
11847                                 events [i].other [j] = mb->mhandle;
11848                         }
11849                 }
11850 #endif
11851                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11852         }
11853 }
11854
11855 static gboolean
11856 remove_instantiations_of_and_ensure_contents (gpointer key,
11857                                                   gpointer value,
11858                                                   gpointer user_data)
11859 {
11860         MonoType *type = (MonoType*)key;
11861         MonoClass *klass = (MonoClass*)user_data;
11862
11863         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11864                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11865                 return TRUE;
11866         } else
11867                 return FALSE;
11868 }
11869
11870 static void
11871 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11872 {
11873         mono_error_init (error);
11874         int i;
11875
11876         if (!arr)
11877                 return;
11878
11879         for (i = 0; i < mono_array_length (arr); ++i) {
11880                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11881                 if (!mono_error_ok (error))
11882                         break;
11883         }
11884 }
11885
11886 MonoReflectionType*
11887 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11888 {
11889         MonoError error;
11890         MonoClass *klass;
11891         MonoDomain* domain;
11892         MonoReflectionType* res;
11893         int i, j;
11894
11895         domain = mono_object_domain (tb);
11896         klass = mono_class_from_mono_type (tb->type.type);
11897
11898         /*
11899          * Check for user defined Type subclasses.
11900          */
11901         RESOLVE_TYPE (tb->parent, &error);
11902         mono_error_raise_exception (&error); /* FIXME don't raise here */
11903         check_array_for_usertypes (tb->interfaces, &error);
11904         mono_error_raise_exception (&error); /*FIXME don't raise here */
11905         if (tb->fields) {
11906                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11907                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11908                         if (fb) {
11909                                 RESOLVE_TYPE (fb->type, &error);
11910                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11911                                 check_array_for_usertypes (fb->modreq, &error);
11912                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11913                                 check_array_for_usertypes (fb->modopt, &error);
11914                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11915                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11916                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11917                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11918                                 }
11919                         }
11920                 }
11921         }
11922         if (tb->methods) {
11923                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11924                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11925                         if (mb) {
11926                                 RESOLVE_TYPE (mb->rtype, &error);
11927                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11928                                 check_array_for_usertypes (mb->return_modreq, &error);
11929                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11930                                 check_array_for_usertypes (mb->return_modopt, &error);
11931                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11932                                 check_array_for_usertypes (mb->parameters, &error);
11933                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11934                                 if (mb->param_modreq)
11935                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11936                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11937                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11938                                         }
11939                                 if (mb->param_modopt)
11940                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11941                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11942                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11943                                         }
11944                         }
11945                 }
11946         }
11947         if (tb->ctors) {
11948                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11949                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11950                         if (mb) {
11951                                 check_array_for_usertypes (mb->parameters, &error);
11952                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11953                                 if (mb->param_modreq)
11954                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11955                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11956                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11957                                         }
11958                                 if (mb->param_modopt)
11959                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11960                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11961                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11962                                         }
11963                         }
11964                 }
11965         }
11966
11967         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11968
11969         /* 
11970          * we need to lock the domain because the lock will be taken inside
11971          * So, we need to keep the locking order correct.
11972          */
11973         mono_loader_lock ();
11974         mono_domain_lock (domain);
11975         if (klass->wastypebuilder) {
11976                 mono_domain_unlock (domain);
11977                 mono_loader_unlock ();
11978
11979                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11980                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11981
11982                 return res;
11983         }
11984         /*
11985          * Fields to set in klass:
11986          * the various flags: delegate/unicode/contextbound etc.
11987          */
11988         klass->flags = tb->attrs;
11989         klass->has_cctor = 1;
11990         klass->has_finalize = 1;
11991         klass->has_finalize_inited = 1;
11992
11993         mono_class_setup_parent (klass, klass->parent);
11994         /* fool mono_class_setup_supertypes */
11995         klass->supertypes = NULL;
11996         mono_class_setup_supertypes (klass);
11997         mono_class_setup_mono_type (klass);
11998
11999 #if 0
12000         if (!((MonoDynamicImage*)klass->image)->run) {
12001                 if (klass->generic_container) {
12002                         /* FIXME: The code below can't handle generic classes */
12003                         klass->wastypebuilder = TRUE;
12004                         mono_loader_unlock ();
12005                         mono_domain_unlock (domain);
12006
12007                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12008                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12009
12010                         return res;
12011                 }
12012         }
12013 #endif
12014
12015         /* enums are done right away */
12016         if (!klass->enumtype)
12017                 ensure_runtime_vtable (klass);
12018
12019         if (tb->subtypes) {
12020                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12021                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12022                         mono_class_alloc_ext (klass);
12023                         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)));
12024                 }
12025         }
12026
12027         klass->nested_classes_inited = TRUE;
12028
12029         /* fields and object layout */
12030         if (klass->parent) {
12031                 if (!klass->parent->size_inited)
12032                         mono_class_init (klass->parent);
12033                 klass->instance_size = klass->parent->instance_size;
12034                 klass->sizes.class_size = 0;
12035                 klass->min_align = klass->parent->min_align;
12036                 /* if the type has no fields we won't call the field_setup
12037                  * routine which sets up klass->has_references.
12038                  */
12039                 klass->has_references |= klass->parent->has_references;
12040         } else {
12041                 klass->instance_size = sizeof (MonoObject);
12042                 klass->min_align = 1;
12043         }
12044
12045         /* FIXME: handle packing_size and instance_size */
12046         typebuilder_setup_fields (klass, &error);
12047         if (!mono_error_ok (&error))
12048                 goto failure;
12049         typebuilder_setup_properties (klass, &error);
12050         if (!mono_error_ok (&error))
12051                 goto failure;
12052
12053         typebuilder_setup_events (klass, &error);
12054         if (!mono_error_ok (&error))
12055                 goto failure;
12056
12057         klass->wastypebuilder = TRUE;
12058
12059         /* 
12060          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12061          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12062          * we want to return normal System.MonoType objects, so clear these out from the cache.
12063          *
12064          * Together with this we must ensure the contents of all instances to match the created type.
12065          */
12066         if (domain->type_hash && klass->generic_container)
12067                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12068
12069         mono_domain_unlock (domain);
12070         mono_loader_unlock ();
12071
12072         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12073                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12074                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12075         }
12076
12077         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12078         mono_error_raise_exception (&error); /* FIXME don't raise here */
12079
12080         g_assert (res != (MonoReflectionType*)tb);
12081
12082         return res;
12083
12084 failure:
12085         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12086         klass->wastypebuilder = TRUE;
12087         mono_domain_unlock (domain);
12088         mono_loader_unlock ();
12089         mono_error_raise_exception (&error);
12090         return NULL;
12091 }
12092
12093 void
12094 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12095 {
12096         MonoGenericParamFull *param;
12097         MonoImage *image;
12098         MonoClass *pklass;
12099         MonoError error;
12100
12101         image = &gparam->tbuilder->module->dynamic_image->image;
12102
12103         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12104
12105         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12106         g_assert (mono_error_ok (&error));
12107         param->param.num = gparam->index;
12108
12109         if (gparam->mbuilder) {
12110                 if (!gparam->mbuilder->generic_container) {
12111                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12112                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12113                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12114                         gparam->mbuilder->generic_container->is_method = TRUE;
12115                         /* 
12116                          * Cannot set owner.method, since the MonoMethod is not created yet.
12117                          * Set the image field instead, so type_in_image () works.
12118                          */
12119                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12120                         gparam->mbuilder->generic_container->owner.image = klass->image;
12121                 }
12122                 param->param.owner = gparam->mbuilder->generic_container;
12123         } else if (gparam->tbuilder) {
12124                 if (!gparam->tbuilder->generic_container) {
12125                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12126                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12127                         gparam->tbuilder->generic_container->owner.klass = klass;
12128                 }
12129                 param->param.owner = gparam->tbuilder->generic_container;
12130         }
12131
12132         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12133
12134         gparam->type.type = &pklass->byval_arg;
12135
12136         mono_class_set_ref_info (pklass, gparam);
12137         mono_image_append_class_to_reflection_info_set (pklass);
12138 }
12139
12140 MonoArray *
12141 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12142 {
12143         MonoError error;
12144         MonoReflectionModuleBuilder *module = sig->module;
12145         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12146         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12147         guint32 buflen, i;
12148         MonoArray *result;
12149         SigBuffer buf;
12150
12151         check_array_for_usertypes (sig->arguments, &error);
12152         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12153
12154         sigbuffer_init (&buf, 32);
12155
12156         sigbuffer_add_value (&buf, 0x07);
12157         sigbuffer_add_value (&buf, na);
12158         if (assembly != NULL){
12159                 for (i = 0; i < na; ++i) {
12160                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12161                         encode_reflection_type (assembly, type, &buf);
12162                 }
12163         }
12164
12165         buflen = buf.p - buf.buf;
12166         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12167         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12168         sigbuffer_free (&buf);
12169
12170         return result;
12171 }
12172
12173 MonoArray *
12174 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12175 {
12176         MonoError error;
12177         MonoDynamicImage *assembly = sig->module->dynamic_image;
12178         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12179         guint32 buflen, i;
12180         MonoArray *result;
12181         SigBuffer buf;
12182
12183         check_array_for_usertypes (sig->arguments, &error);
12184         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12185
12186         sigbuffer_init (&buf, 32);
12187
12188         sigbuffer_add_value (&buf, 0x06);
12189         for (i = 0; i < na; ++i) {
12190                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12191                 encode_reflection_type (assembly, type, &buf);
12192         }
12193
12194         buflen = buf.p - buf.buf;
12195         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12196         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12197         sigbuffer_free (&buf);
12198
12199         return result;
12200 }
12201
12202 typedef struct {
12203         MonoMethod *handle;
12204         MonoDomain *domain;
12205 } DynamicMethodReleaseData;
12206
12207 /*
12208  * The runtime automatically clean up those after finalization.
12209 */      
12210 static MonoReferenceQueue *dynamic_method_queue;
12211
12212 static void
12213 free_dynamic_method (void *dynamic_method)
12214 {
12215         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12216         MonoDomain *domain = data->domain;
12217         MonoMethod *method = data->handle;
12218         guint32 dis_link;
12219
12220         mono_domain_lock (domain);
12221         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12222         g_hash_table_remove (domain->method_to_dyn_method, method);
12223         mono_domain_unlock (domain);
12224         g_assert (dis_link);
12225         mono_gchandle_free (dis_link);
12226
12227         mono_runtime_free_method (domain, method);
12228         g_free (data);
12229 }
12230
12231 void 
12232 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12233 {
12234         MonoReferenceQueue *queue;
12235         MonoMethod *handle;
12236         DynamicMethodReleaseData *release_data;
12237         ReflectionMethodBuilder rmb;
12238         MonoMethodSignature *sig;
12239         MonoClass *klass;
12240         MonoDomain *domain;
12241         GSList *l;
12242         int i;
12243
12244         if (mono_runtime_is_shutting_down ())
12245                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12246
12247         if (!(queue = dynamic_method_queue)) {
12248                 mono_loader_lock ();
12249                 if (!(queue = dynamic_method_queue))
12250                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12251                 mono_loader_unlock ();
12252         }
12253
12254         sig = dynamic_method_to_signature (mb);
12255
12256         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12257
12258         /*
12259          * Resolve references.
12260          */
12261         /* 
12262          * Every second entry in the refs array is reserved for storing handle_class,
12263          * which is needed by the ldtoken implementation in the JIT.
12264          */
12265         rmb.nrefs = mb->nrefs;
12266         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12267         for (i = 0; i < mb->nrefs; i += 2) {
12268                 MonoClass *handle_class;
12269                 gpointer ref;
12270                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12271
12272                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12273                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12274                         /*
12275                          * The referenced DynamicMethod should already be created by the managed
12276                          * code, except in the case of circular references. In that case, we store
12277                          * method in the refs array, and fix it up later when the referenced 
12278                          * DynamicMethod is created.
12279                          */
12280                         if (method->mhandle) {
12281                                 ref = method->mhandle;
12282                         } else {
12283                                 /* FIXME: GC object stored in unmanaged memory */
12284                                 ref = method;
12285
12286                                 /* FIXME: GC object stored in unmanaged memory */
12287                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12288                         }
12289                         handle_class = mono_defaults.methodhandle_class;
12290                 } else {
12291                         MonoException *ex = NULL;
12292                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12293                         if (!ref)
12294                                 ex = mono_get_exception_type_load (NULL, NULL);
12295                         else if (mono_security_core_clr_enabled ())
12296                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12297
12298                         if (ex) {
12299                                 g_free (rmb.refs);
12300                                 mono_raise_exception (ex);
12301                                 return;
12302                         }
12303                 }
12304
12305                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12306                 rmb.refs [i + 1] = handle_class;
12307         }               
12308
12309         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12310
12311         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12312         release_data = g_new (DynamicMethodReleaseData, 1);
12313         release_data->handle = handle;
12314         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12315         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12316                 g_free (release_data);
12317
12318         /* Fix up refs entries pointing at us */
12319         for (l = mb->referenced_by; l; l = l->next) {
12320                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12321                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12322                 gpointer *data;
12323                 
12324                 g_assert (method->mhandle);
12325
12326                 data = (gpointer*)wrapper->method_data;
12327                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12328                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12329                                 data [i + 1] = mb->mhandle;
12330                 }
12331         }
12332         g_slist_free (mb->referenced_by);
12333
12334         g_free (rmb.refs);
12335
12336         /* ilgen is no longer needed */
12337         mb->ilgen = NULL;
12338
12339         domain = mono_domain_get ();
12340         mono_domain_lock (domain);
12341         if (!domain->method_to_dyn_method)
12342                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12343         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12344         mono_domain_unlock (domain);
12345 }
12346
12347 #endif /* DISABLE_REFLECTION_EMIT */
12348
12349 /**
12350  * 
12351  * mono_reflection_is_valid_dynamic_token:
12352  * 
12353  * Returns TRUE if token is valid.
12354  * 
12355  */
12356 gboolean
12357 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12358 {
12359         return lookup_dyn_token (image, token) != NULL;
12360 }
12361
12362 MonoMethodSignature *
12363 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12364 {
12365         MonoMethodSignature *sig;
12366         g_assert (image_is_dynamic (image));
12367
12368         mono_error_init (error);
12369
12370         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12371         if (sig)
12372                 return sig;
12373
12374         return mono_method_signature_checked (method, error);
12375 }
12376
12377 #ifndef DISABLE_REFLECTION_EMIT
12378
12379 /**
12380  * mono_reflection_lookup_dynamic_token:
12381  *
12382  * Finish the Builder object pointed to by TOKEN and return the corresponding
12383  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12384  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12385  * mapping table.
12386  *
12387  * LOCKING: Take the loader lock
12388  */
12389 gpointer
12390 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12391 {
12392         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12393         MonoObject *obj;
12394         MonoClass *klass;
12395
12396         obj = lookup_dyn_token (assembly, token);
12397         if (!obj) {
12398                 if (valid_token)
12399                         g_error ("Could not find required dynamic token 0x%08x", token);
12400                 else
12401                         return NULL;
12402         }
12403
12404         if (!handle_class)
12405                 handle_class = &klass;
12406         return resolve_object (image, obj, handle_class, context);
12407 }
12408
12409 /*
12410  * ensure_complete_type:
12411  *
12412  *   Ensure that KLASS is completed if it is a dynamic type, or references
12413  * dynamic types.
12414  */
12415 static void
12416 ensure_complete_type (MonoClass *klass)
12417 {
12418         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12419                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12420
12421                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12422
12423                 // Asserting here could break a lot of code
12424                 //g_assert (klass->wastypebuilder);
12425         }
12426
12427         if (klass->generic_class) {
12428                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12429                 int i;
12430
12431                 for (i = 0; i < inst->type_argc; ++i) {
12432                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12433                 }
12434         }
12435 }
12436
12437 static gpointer
12438 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12439 {
12440         gpointer result = NULL;
12441
12442         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12443                 result = mono_string_intern ((MonoString*)obj);
12444                 *handle_class = mono_defaults.string_class;
12445                 g_assert (result);
12446         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12447                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12448                 MonoClass *mc = mono_class_from_mono_type (type);
12449                 if (!mono_class_init (mc))
12450                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12451
12452                 if (context) {
12453                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12454                         result = mono_class_from_mono_type (inflated);
12455                         mono_metadata_free_type (inflated);
12456                 } else {
12457                         result = mono_class_from_mono_type (type);
12458                 }
12459                 *handle_class = mono_defaults.typehandle_class;
12460                 g_assert (result);
12461         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12462                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12463                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12464                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12465                 result = ((MonoReflectionMethod*)obj)->method;
12466                 if (context) {
12467                         MonoError error;
12468                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12469                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12470                 }
12471                 *handle_class = mono_defaults.methodhandle_class;
12472                 g_assert (result);
12473         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12474                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12475                 result = mb->mhandle;
12476                 if (!result) {
12477                         /* Type is not yet created */
12478                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12479
12480                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12481
12482                         /*
12483                          * Hopefully this has been filled in by calling CreateType() on the
12484                          * TypeBuilder.
12485                          */
12486                         /*
12487                          * TODO: This won't work if the application finishes another 
12488                          * TypeBuilder instance instead of this one.
12489                          */
12490                         result = mb->mhandle;
12491                 }
12492                 if (context) {
12493                         MonoError error;
12494                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12495                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12496                 }
12497                 *handle_class = mono_defaults.methodhandle_class;
12498         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12499                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12500
12501                 result = cb->mhandle;
12502                 if (!result) {
12503                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12504
12505                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12506                         result = cb->mhandle;
12507                 }
12508                 if (context) {
12509                         MonoError error;
12510                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12511                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12512                 }
12513                 *handle_class = mono_defaults.methodhandle_class;
12514         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12515                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12516
12517                 ensure_complete_type (field->parent);
12518                 if (context) {
12519                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12520                         MonoClass *klass = mono_class_from_mono_type (inflated);
12521                         MonoClassField *inflated_field;
12522                         gpointer iter = NULL;
12523                         mono_metadata_free_type (inflated);
12524                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12525                                 if (!strcmp (field->name, inflated_field->name))
12526                                         break;
12527                         }
12528                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12529                         result = inflated_field;
12530                 } else {
12531                         result = field;
12532                 }
12533                 *handle_class = mono_defaults.fieldhandle_class;
12534                 g_assert (result);
12535         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12536                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12537                 result = fb->handle;
12538
12539                 if (!result) {
12540                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12541
12542                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12543                         result = fb->handle;
12544                 }
12545
12546                 if (fb->handle && fb->handle->parent->generic_container) {
12547                         MonoClass *klass = fb->handle->parent;
12548                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12549                         MonoClass *inflated = mono_class_from_mono_type (type);
12550
12551                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12552                         g_assert (result);
12553                         mono_metadata_free_type (type);
12554                 }
12555                 *handle_class = mono_defaults.fieldhandle_class;
12556         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12557                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12558                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12559                 MonoClass *klass;
12560
12561                 klass = type->data.klass;
12562                 if (klass->wastypebuilder) {
12563                         /* Already created */
12564                         result = klass;
12565                 }
12566                 else {
12567                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12568                         result = type->data.klass;
12569                         g_assert (result);
12570                 }
12571                 *handle_class = mono_defaults.typehandle_class;
12572         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12573                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12574                 MonoMethodSignature *sig;
12575                 int nargs, i;
12576
12577                 if (helper->arguments)
12578                         nargs = mono_array_length (helper->arguments);
12579                 else
12580                         nargs = 0;
12581
12582                 sig = mono_metadata_signature_alloc (image, nargs);
12583                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12584                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12585
12586                 if (helper->unmanaged_call_conv) { /* unmanaged */
12587                         sig->call_convention = helper->unmanaged_call_conv - 1;
12588                         sig->pinvoke = TRUE;
12589                 } else if (helper->call_conv & 0x02) {
12590                         sig->call_convention = MONO_CALL_VARARG;
12591                 } else {
12592                         sig->call_convention = MONO_CALL_DEFAULT;
12593                 }
12594
12595                 sig->param_count = nargs;
12596                 /* TODO: Copy type ? */
12597                 sig->ret = helper->return_type->type;
12598                 for (i = 0; i < nargs; ++i)
12599                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12600
12601                 result = sig;
12602                 *handle_class = NULL;
12603         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12604                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12605                 /* Already created by the managed code */
12606                 g_assert (method->mhandle);
12607                 result = method->mhandle;
12608                 *handle_class = mono_defaults.methodhandle_class;
12609         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12610                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12611                 type = mono_class_inflate_generic_type (type, context);
12612                 result = mono_class_from_mono_type (type);
12613                 *handle_class = mono_defaults.typehandle_class;
12614                 g_assert (result);
12615                 mono_metadata_free_type (type);
12616         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12617                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12618                 type = mono_class_inflate_generic_type (type, context);
12619                 result = mono_class_from_mono_type (type);
12620                 *handle_class = mono_defaults.typehandle_class;
12621                 g_assert (result);
12622                 mono_metadata_free_type (type);
12623         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12624                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12625                 MonoClass *inflated;
12626                 MonoType *type;
12627                 MonoClassField *field;
12628
12629                 if (is_sre_field_builder (mono_object_class (f->fb)))
12630                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12631                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12632                         field = ((MonoReflectionField*)f->fb)->field;
12633                 else
12634                         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)));
12635
12636                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12637                 inflated = mono_class_from_mono_type (type);
12638
12639                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12640                 ensure_complete_type (field->parent);
12641                 g_assert (result);
12642                 mono_metadata_free_type (type);
12643                 *handle_class = mono_defaults.fieldhandle_class;
12644         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12645                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12646                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12647                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12648                 MonoMethod *method;
12649
12650                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12651                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12652                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12653                         method = ((MonoReflectionMethod *)c->cb)->method;
12654                 else
12655                         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)));
12656
12657                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12658                 *handle_class = mono_defaults.methodhandle_class;
12659                 mono_metadata_free_type (type);
12660         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12661                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12662                 if (m->method_args) {
12663                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12664                         if (context) {
12665                                 MonoError error;
12666                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12667                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12668                         }
12669                 } else {
12670                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12671                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12672                         MonoMethod *method;
12673
12674                         if (is_sre_method_builder (mono_object_class (m->mb)))
12675                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12676                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12677                                 method = ((MonoReflectionMethod *)m->mb)->method;
12678                         else
12679                                 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)));
12680
12681                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12682                         mono_metadata_free_type (type);
12683                 }
12684                 *handle_class = mono_defaults.methodhandle_class;
12685         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12686                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12687                 MonoType *mtype;
12688                 MonoClass *klass;
12689                 MonoMethod *method;
12690                 gpointer iter;
12691                 char *name;
12692
12693                 mtype = mono_reflection_type_get_handle (m->parent);
12694                 klass = mono_class_from_mono_type (mtype);
12695
12696                 /* Find the method */
12697
12698                 name = mono_string_to_utf8 (m->name);
12699                 iter = NULL;
12700                 while ((method = mono_class_get_methods (klass, &iter))) {
12701                         if (!strcmp (method->name, name))
12702                                 break;
12703                 }
12704                 g_free (name);
12705
12706                 // FIXME:
12707                 g_assert (method);
12708                 // FIXME: Check parameters/return value etc. match
12709
12710                 result = method;
12711                 *handle_class = mono_defaults.methodhandle_class;
12712         } else if (is_sre_array (mono_object_get_class(obj)) ||
12713                                 is_sre_byref (mono_object_get_class(obj)) ||
12714                                 is_sre_pointer (mono_object_get_class(obj))) {
12715                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12716                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12717
12718                 if (context) {
12719                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12720                         result = mono_class_from_mono_type (inflated);
12721                         mono_metadata_free_type (inflated);
12722                 } else {
12723                         result = mono_class_from_mono_type (type);
12724                 }
12725                 *handle_class = mono_defaults.typehandle_class;
12726         } else {
12727                 g_print ("%s\n", obj->vtable->klass->name);
12728                 g_assert_not_reached ();
12729         }
12730         return result;
12731 }
12732
12733 #else /* DISABLE_REFLECTION_EMIT */
12734
12735 MonoArray*
12736 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12737 {
12738         g_assert_not_reached ();
12739         return NULL;
12740 }
12741
12742 void
12743 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12744 {
12745         g_assert_not_reached ();
12746 }
12747
12748 void
12749 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12750 {
12751         g_assert_not_reached ();
12752 }
12753
12754 void
12755 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12756 {
12757         g_assert_not_reached ();
12758 }
12759
12760 void
12761 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12762 {
12763         g_assert_not_reached ();
12764 }
12765
12766 void
12767 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12768 {
12769         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12770 }
12771
12772 void
12773 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12774 {
12775         g_assert_not_reached ();
12776 }
12777
12778 void
12779 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12780 {
12781         g_assert_not_reached ();
12782 }
12783
12784 MonoReflectionModule *
12785 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12786 {
12787         g_assert_not_reached ();
12788         return NULL;
12789 }
12790
12791 guint32
12792 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12793 {
12794         g_assert_not_reached ();
12795         return 0;
12796 }
12797
12798 guint32
12799 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12800 {
12801         g_assert_not_reached ();
12802         return 0;
12803 }
12804
12805 guint32
12806 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12807                                                  gboolean create_open_instance, gboolean register_token)
12808 {
12809         g_assert_not_reached ();
12810         return 0;
12811 }
12812
12813 void
12814 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12815 {
12816 }
12817
12818 void
12819 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12820 {
12821         g_assert_not_reached ();
12822 }
12823
12824 void
12825 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12826 {
12827         *overrides = NULL;
12828         *num_overrides = 0;
12829 }
12830
12831 MonoReflectionEvent *
12832 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12833 {
12834         g_assert_not_reached ();
12835         return NULL;
12836 }
12837
12838 MonoReflectionType*
12839 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12840 {
12841         g_assert_not_reached ();
12842         return NULL;
12843 }
12844
12845 void
12846 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12847 {
12848         g_assert_not_reached ();
12849 }
12850
12851 MonoArray *
12852 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12853 {
12854         g_assert_not_reached ();
12855         return NULL;
12856 }
12857
12858 MonoArray *
12859 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12860 {
12861         g_assert_not_reached ();
12862         return NULL;
12863 }
12864
12865 void 
12866 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12867 {
12868 }
12869
12870 gpointer
12871 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12872 {
12873         return NULL;
12874 }
12875
12876 MonoType*
12877 mono_reflection_type_get_handle (MonoReflectionType* ref)
12878 {
12879         if (!ref)
12880                 return NULL;
12881         return ref->type;
12882 }
12883
12884 void
12885 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12886 {
12887         g_assert_not_reached ();
12888 }
12889
12890 #endif /* DISABLE_REFLECTION_EMIT */
12891
12892 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12893 const static guint32 declsec_flags_map[] = {
12894         0x00000000,                                     /* empty */
12895         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12896         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12897         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12898         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12899         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12900         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12901         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12902         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12903         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12904         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12905         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12906         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12907         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12908         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12909         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12910         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12911         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12912         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12913 };
12914
12915 /*
12916  * Returns flags that includes all available security action associated to the handle.
12917  * @token: metadata token (either for a class or a method)
12918  * @image: image where resides the metadata.
12919  */
12920 static guint32
12921 mono_declsec_get_flags (MonoImage *image, guint32 token)
12922 {
12923         int index = mono_metadata_declsec_from_index (image, token);
12924         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12925         guint32 result = 0;
12926         guint32 action;
12927         int i;
12928
12929         /* HasSecurity can be present for other, not specially encoded, attributes,
12930            e.g. SuppressUnmanagedCodeSecurityAttribute */
12931         if (index < 0)
12932                 return 0;
12933
12934         for (i = index; i < t->rows; i++) {
12935                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12936
12937                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12938                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12939                         break;
12940
12941                 action = cols [MONO_DECL_SECURITY_ACTION];
12942                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12943                         result |= declsec_flags_map [action];
12944                 } else {
12945                         g_assert_not_reached ();
12946                 }
12947         }
12948         return result;
12949 }
12950
12951 /*
12952  * Get the security actions (in the form of flags) associated with the specified method.
12953  *
12954  * @method: The method for which we want the declarative security flags.
12955  * Return the declarative security flags for the method (only).
12956  *
12957  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12958  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12959  */
12960 guint32
12961 mono_declsec_flags_from_method (MonoMethod *method)
12962 {
12963         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12964                 /* FIXME: No cache (for the moment) */
12965                 guint32 idx = mono_method_get_index (method);
12966                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12967                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12968                 return mono_declsec_get_flags (method->klass->image, idx);
12969         }
12970         return 0;
12971 }
12972
12973 /*
12974  * Get the security actions (in the form of flags) associated with the specified class.
12975  *
12976  * @klass: The class for which we want the declarative security flags.
12977  * Return the declarative security flags for the class.
12978  *
12979  * Note: We cache the flags inside the MonoClass structure as this will get 
12980  *       called very often (at least for each method).
12981  */
12982 guint32
12983 mono_declsec_flags_from_class (MonoClass *klass)
12984 {
12985         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12986                 if (!klass->ext || !klass->ext->declsec_flags) {
12987                         guint32 idx;
12988
12989                         idx = mono_metadata_token_index (klass->type_token);
12990                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12991                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12992                         mono_loader_lock ();
12993                         mono_class_alloc_ext (klass);
12994                         mono_loader_unlock ();
12995                         /* we cache the flags on classes */
12996                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12997                 }
12998                 return klass->ext->declsec_flags;
12999         }
13000         return 0;
13001 }
13002
13003 /*
13004  * Get the security actions (in the form of flags) associated with the specified assembly.
13005  *
13006  * @assembly: The assembly for which we want the declarative security flags.
13007  * Return the declarative security flags for the assembly.
13008  */
13009 guint32
13010 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13011 {
13012         guint32 idx = 1; /* there is only one assembly */
13013         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13014         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13015         return mono_declsec_get_flags (assembly->image, idx);
13016 }
13017
13018
13019 /*
13020  * Fill actions for the specific index (which may either be an encoded class token or
13021  * an encoded method token) from the metadata image.
13022  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13023  */
13024 static MonoBoolean
13025 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13026         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13027 {
13028         MonoBoolean result = FALSE;
13029         MonoTableInfo *t;
13030         guint32 cols [MONO_DECL_SECURITY_SIZE];
13031         int index = mono_metadata_declsec_from_index (image, token);
13032         int i;
13033
13034         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13035         for (i = index; i < t->rows; i++) {
13036                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13037
13038                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13039                         return result;
13040
13041                 /* if present only replace (class) permissions with method permissions */
13042                 /* if empty accept either class or method permissions */
13043                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13044                         if (!actions->demand.blob) {
13045                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13046                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13047                                 actions->demand.blob = (char*) (blob + 2);
13048                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13049                                 result = TRUE;
13050                         }
13051                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13052                         if (!actions->noncasdemand.blob) {
13053                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13054                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13055                                 actions->noncasdemand.blob = (char*) (blob + 2);
13056                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13057                                 result = TRUE;
13058                         }
13059                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13060                         if (!actions->demandchoice.blob) {
13061                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13062                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13063                                 actions->demandchoice.blob = (char*) (blob + 2);
13064                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13065                                 result = TRUE;
13066                         }
13067                 }
13068         }
13069
13070         return result;
13071 }
13072
13073 static MonoBoolean
13074 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13075         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13076 {
13077         guint32 idx = mono_metadata_token_index (klass->type_token);
13078         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13079         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13080         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13081 }
13082
13083 static MonoBoolean
13084 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13085         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13086 {
13087         guint32 idx = mono_method_get_index (method);
13088         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13089         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13090         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13091 }
13092
13093 /*
13094  * Collect all actions (that requires to generate code in mini) assigned for
13095  * the specified method.
13096  * Note: Don't use the content of actions if the function return FALSE.
13097  */
13098 MonoBoolean
13099 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13100 {
13101         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13102                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13103         MonoBoolean result = FALSE;
13104         guint32 flags;
13105
13106         /* quick exit if no declarative security is present in the metadata */
13107         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13108                 return FALSE;
13109
13110         /* we want the original as the wrapper is "free" of the security informations */
13111         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13112                 method = mono_marshal_method_from_wrapper (method);
13113                 if (!method)
13114                         return FALSE;
13115         }
13116
13117         /* First we look for method-level attributes */
13118         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13119                 mono_class_init (method->klass);
13120                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13121
13122                 result = mono_declsec_get_method_demands_params (method, demands, 
13123                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13124         }
13125
13126         /* Here we use (or create) the class declarative cache to look for demands */
13127         flags = mono_declsec_flags_from_class (method->klass);
13128         if (flags & mask) {
13129                 if (!result) {
13130                         mono_class_init (method->klass);
13131                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13132                 }
13133                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13134                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13135         }
13136
13137         /* The boolean return value is used as a shortcut in case nothing needs to
13138            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13139         return result;
13140 }
13141
13142
13143 /*
13144  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13145  *
13146  * Note: Don't use the content of actions if the function return FALSE.
13147  */
13148 MonoBoolean
13149 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13150 {
13151         MonoBoolean result = FALSE;
13152         guint32 flags;
13153
13154         /* quick exit if no declarative security is present in the metadata */
13155         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13156                 return FALSE;
13157
13158         /* we want the original as the wrapper is "free" of the security informations */
13159         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13160                 method = mono_marshal_method_from_wrapper (method);
13161                 if (!method)
13162                         return FALSE;
13163         }
13164
13165         /* results are independant - zeroize both */
13166         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13167         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13168
13169         /* First we look for method-level attributes */
13170         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13171                 mono_class_init (method->klass);
13172
13173                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13174                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13175         }
13176
13177         /* Here we use (or create) the class declarative cache to look for demands */
13178         flags = mono_declsec_flags_from_class (method->klass);
13179         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13180                 mono_class_init (method->klass);
13181
13182                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13183                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13184         }
13185
13186         return result;
13187 }
13188
13189 /*
13190  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13191  *
13192  * @klass       The inherited class - this is the class that provides the security check (attributes)
13193  * @demans      
13194  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13195  * 
13196  * Note: Don't use the content of actions if the function return FALSE.
13197  */
13198 MonoBoolean
13199 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13200 {
13201         MonoBoolean result = FALSE;
13202         guint32 flags;
13203
13204         /* quick exit if no declarative security is present in the metadata */
13205         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13206                 return FALSE;
13207
13208         /* Here we use (or create) the class declarative cache to look for demands */
13209         flags = mono_declsec_flags_from_class (klass);
13210         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13211                 mono_class_init (klass);
13212                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13213
13214                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13215                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13216         }
13217
13218         return result;
13219 }
13220
13221 /*
13222  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13223  *
13224  * Note: Don't use the content of actions if the function return FALSE.
13225  */
13226 MonoBoolean
13227 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13228 {
13229         /* quick exit if no declarative security is present in the metadata */
13230         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13231                 return FALSE;
13232
13233         /* we want the original as the wrapper is "free" of the security informations */
13234         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13235                 method = mono_marshal_method_from_wrapper (method);
13236                 if (!method)
13237                         return FALSE;
13238         }
13239
13240         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13241                 mono_class_init (method->klass);
13242                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13243
13244                 return mono_declsec_get_method_demands_params (method, demands, 
13245                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13246         }
13247         return FALSE;
13248 }
13249
13250
13251 static MonoBoolean
13252 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13253 {
13254         guint32 cols [MONO_DECL_SECURITY_SIZE];
13255         MonoTableInfo *t;
13256         int i;
13257
13258         int index = mono_metadata_declsec_from_index (image, token);
13259         if (index == -1)
13260                 return FALSE;
13261
13262         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13263         for (i = index; i < t->rows; i++) {
13264                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13265
13266                 /* shortcut - index are ordered */
13267                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13268                         return FALSE;
13269
13270                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13271                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13272                         entry->blob = (char*) (metadata + 2);
13273                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13274                         return TRUE;
13275                 }
13276         }
13277
13278         return FALSE;
13279 }
13280
13281 MonoBoolean
13282 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13283 {
13284         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13285                 guint32 idx = mono_method_get_index (method);
13286                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13287                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13288                 return get_declsec_action (method->klass->image, idx, action, entry);
13289         }
13290         return FALSE;
13291 }
13292
13293 MonoBoolean
13294 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13295 {
13296         /* use cache */
13297         guint32 flags = mono_declsec_flags_from_class (klass);
13298         if (declsec_flags_map [action] & flags) {
13299                 guint32 idx = mono_metadata_token_index (klass->type_token);
13300                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13301                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13302                 return get_declsec_action (klass->image, idx, action, entry);
13303         }
13304         return FALSE;
13305 }
13306
13307 MonoBoolean
13308 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13309 {
13310         guint32 idx = 1; /* there is only one assembly */
13311         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13312         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13313
13314         return get_declsec_action (assembly->image, idx, action, entry);
13315 }
13316
13317 gboolean
13318 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13319 {
13320         MonoError error;
13321         MonoObject *res, *exc;
13322         void *params [1];
13323         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13324         static MonoMethod *method = NULL;
13325
13326         if (!System_Reflection_Emit_TypeBuilder) {
13327                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13328                 g_assert (System_Reflection_Emit_TypeBuilder);
13329         }
13330         if (method == NULL) {
13331                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13332                 g_assert (method);
13333         }
13334
13335         /* 
13336          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13337          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13338          */
13339         g_assert (mono_class_get_ref_info (klass));
13340         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13341
13342         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13343         mono_error_raise_exception (&error); /* FIXME don't raise here */
13344
13345         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13346         if (exc)
13347                 return FALSE;
13348         else
13349                 return *(MonoBoolean*)mono_object_unbox (res);
13350 }
13351
13352 /**
13353  * mono_reflection_type_get_type:
13354  * @reftype: the System.Type object
13355  *
13356  * Returns the MonoType* associated with the C# System.Type object @reftype.
13357  */
13358 MonoType*
13359 mono_reflection_type_get_type (MonoReflectionType *reftype)
13360 {
13361         g_assert (reftype);
13362
13363         return mono_reflection_type_get_handle (reftype);
13364 }
13365
13366 /**
13367  * mono_reflection_assembly_get_assembly:
13368  * @refassembly: the System.Reflection.Assembly object
13369  *
13370  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13371  */
13372 MonoAssembly*
13373 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13374 {
13375         g_assert (refassembly);
13376
13377         return refassembly->assembly;
13378 }
13379