Merge pull request #2522 from ludovic-henry/test-socketresponder-task
[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         MonoReflectionType *rt;
6936         MonoReflectionField *res;
6937         static MonoClass *monofield_klass;
6938
6939         CHECK_OBJECT (MonoReflectionField *, field, klass);
6940         if (!monofield_klass)
6941                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6942         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6943         res->klass = klass;
6944         res->field = field;
6945         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6946
6947         if (is_field_on_inst (field)) {
6948                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6949
6950                 rt = mono_type_get_object_checked (domain, field->type, &error);
6951                 mono_error_raise_exception (&error); /* FIXME don't raise here */
6952
6953                 MONO_OBJECT_SETREF (res, type, rt);
6954         } else {
6955                 if (field->type) {
6956                         rt = mono_type_get_object_checked (domain, field->type, &error);
6957                         mono_error_raise_exception (&error); /* FIXME don't raise here */
6958
6959                         MONO_OBJECT_SETREF (res, type, rt);
6960                 }
6961                 res->attrs = mono_field_get_flags (field);
6962         }
6963         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6964 }
6965
6966 /*
6967  * mono_property_get_object:
6968  * @domain: an app domain
6969  * @klass: a type
6970  * @property: a property
6971  *
6972  * Return an System.Reflection.MonoProperty object representing the property @property
6973  * in class @klass.
6974  */
6975 MonoReflectionProperty*
6976 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6977 {
6978         MonoReflectionProperty *res;
6979         static MonoClass *monoproperty_klass;
6980
6981         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6982         if (!monoproperty_klass)
6983                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6984         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6985         res->klass = klass;
6986         res->property = property;
6987         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6988 }
6989
6990 /*
6991  * mono_event_get_object:
6992  * @domain: an app domain
6993  * @klass: a type
6994  * @event: a event
6995  *
6996  * Return an System.Reflection.MonoEvent object representing the event @event
6997  * in class @klass.
6998  */
6999 MonoReflectionEvent*
7000 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7001 {
7002         MonoReflectionEvent *res;
7003         MonoReflectionMonoEvent *mono_event;
7004         static MonoClass *monoevent_klass;
7005
7006         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7007         if (!monoevent_klass)
7008                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
7009         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
7010         mono_event->klass = klass;
7011         mono_event->event = event;
7012         res = (MonoReflectionEvent*)mono_event;
7013         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7014 }
7015
7016 /**
7017  * mono_get_reflection_missing_object:
7018  * @domain: Domain where the object lives
7019  *
7020  * Returns the System.Reflection.Missing.Value singleton object
7021  * (of type System.Reflection.Missing).
7022  *
7023  * Used as the value for ParameterInfo.DefaultValue when Optional
7024  * is present
7025  */
7026 static MonoObject *
7027 mono_get_reflection_missing_object (MonoDomain *domain)
7028 {
7029         MonoObject *obj;
7030         static MonoClassField *missing_value_field = NULL;
7031         
7032         if (!missing_value_field) {
7033                 MonoClass *missing_klass;
7034                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
7035                 mono_class_init (missing_klass);
7036                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7037                 g_assert (missing_value_field);
7038         }
7039         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7040         g_assert (obj);
7041         return obj;
7042 }
7043
7044 static MonoObject*
7045 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7046 {
7047         if (!*dbnull)
7048                 *dbnull = mono_get_dbnull_object (domain);
7049         return *dbnull;
7050 }
7051
7052 static MonoObject*
7053 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7054 {
7055         if (!*reflection_missing)
7056                 *reflection_missing = mono_get_reflection_missing_object (domain);
7057         return *reflection_missing;
7058 }
7059
7060 /*
7061  * mono_param_get_objects:
7062  * @domain: an app domain
7063  * @method: a method
7064  *
7065  * Return an System.Reflection.ParameterInfo array object representing the parameters
7066  * in the method @method.
7067  */
7068 MonoArray*
7069 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7070 {
7071         static MonoClass *System_Reflection_ParameterInfo;
7072         static MonoClass *System_Reflection_ParameterInfo_array;
7073         MonoError error;
7074         MonoArray *res = NULL;
7075         MonoReflectionMethod *member = NULL;
7076         MonoReflectionParameter *param = NULL;
7077         char **names, **blobs = NULL;
7078         guint32 *types = NULL;
7079         MonoType *type = NULL;
7080         MonoObject *dbnull = NULL;
7081         MonoObject *missing = NULL;
7082         MonoMarshalSpec **mspecs;
7083         MonoMethodSignature *sig;
7084         MonoVTable *pinfo_vtable;
7085         MonoReflectionType *rt;
7086         int i;
7087
7088         if (!System_Reflection_ParameterInfo_array) {
7089                 MonoClass *klass;
7090
7091                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7092                 if (!klass)
7093                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7094
7095                 mono_memory_barrier ();
7096                 System_Reflection_ParameterInfo = klass; 
7097
7098         
7099                 klass = mono_array_class_get (klass, 1);
7100                 mono_memory_barrier ();
7101                 System_Reflection_ParameterInfo_array = klass;
7102         }
7103
7104         sig = mono_method_signature_checked (method, &error);
7105         if (!mono_error_ok (&error))
7106                 mono_error_raise_exception (&error);
7107
7108         if (!sig->param_count) {
7109                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7110                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7111
7112                 return res;
7113         }
7114
7115         /* Note: the cache is based on the address of the signature into the method
7116          * since we already cache MethodInfos with the method as keys.
7117          */
7118         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7119
7120         member = mono_method_get_object (domain, method, refclass);
7121         names = g_new (char *, sig->param_count);
7122         mono_method_get_param_names (method, (const char **) names);
7123
7124         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7125         mono_method_get_marshal_info (method, mspecs);
7126
7127         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7128         mono_error_raise_exception (&error); /* FIXME don't raise here */
7129
7130         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7131         for (i = 0; i < sig->param_count; ++i) {
7132                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7133                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7134
7135                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7136                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7137
7138                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7139
7140                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7141
7142                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7143
7144                 param->PositionImpl = i;
7145                 param->AttrsImpl = sig->params [i]->attrs;
7146
7147                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7148                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7149                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7150                         else
7151                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7152                 } else {
7153
7154                         if (!blobs) {
7155                                 blobs = g_new0 (char *, sig->param_count);
7156                                 types = g_new0 (guint32, sig->param_count);
7157                                 get_default_param_value_blobs (method, blobs, types); 
7158                         }
7159
7160                         /* Build MonoType for the type from the Constant Table */
7161                         if (!type)
7162                                 type = g_new0 (MonoType, 1);
7163                         type->type = (MonoTypeEnum)types [i];
7164                         type->data.klass = NULL;
7165                         if (types [i] == MONO_TYPE_CLASS)
7166                                 type->data.klass = mono_defaults.object_class;
7167                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7168                                 /* For enums, types [i] contains the base type */
7169
7170                                         type->type = MONO_TYPE_VALUETYPE;
7171                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7172                         } else
7173                                 type->data.klass = mono_class_from_mono_type (type);
7174
7175                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7176
7177                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7178                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7179                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7180                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7181                                 else
7182                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7183                         }
7184                         
7185                 }
7186
7187                 if (mspecs [i + 1])
7188                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7189                 
7190                 mono_array_setref (res, i, param);
7191         }
7192         g_free (names);
7193         g_free (blobs);
7194         g_free (types);
7195         g_free (type);
7196
7197         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7198                 if (mspecs [i])
7199                         mono_metadata_free_marshal_spec (mspecs [i]);
7200         g_free (mspecs);
7201         
7202         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7203 }
7204
7205 MonoArray*
7206 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7207 {
7208         return mono_param_get_objects_internal (domain, method, NULL);
7209 }
7210
7211 /*
7212  * mono_method_body_get_object:
7213  * @domain: an app domain
7214  * @method: a method
7215  *
7216  * Return an System.Reflection.MethodBody object representing the method @method.
7217  */
7218 MonoReflectionMethodBody*
7219 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7220 {
7221         static MonoClass *System_Reflection_MethodBody = NULL;
7222         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7223         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7224         MonoError error;
7225         MonoReflectionMethodBody *ret;
7226         MonoMethodHeader *header;
7227         MonoImage *image;
7228         MonoReflectionType *rt;
7229         guint32 method_rva, local_var_sig_token;
7230     char *ptr;
7231         unsigned char format, flags;
7232         int i;
7233
7234         /* for compatibility with .net */
7235     if (method_is_dynamic (method))
7236         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7237
7238         if (!System_Reflection_MethodBody)
7239                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7240         if (!System_Reflection_LocalVariableInfo)
7241                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7242         if (!System_Reflection_ExceptionHandlingClause)
7243                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7244
7245         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7246
7247         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7248                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7249             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7250                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7251             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7252                 return NULL;
7253
7254         image = method->klass->image;
7255         header = mono_method_get_header (method);
7256
7257         if (!image_is_dynamic (image)) {
7258                 /* Obtain local vars signature token */
7259                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7260                 ptr = mono_image_rva_map (image, method_rva);
7261                 flags = *(const unsigned char *) ptr;
7262                 format = flags & METHOD_HEADER_FORMAT_MASK;
7263                 switch (format){
7264                 case METHOD_HEADER_TINY_FORMAT:
7265                         local_var_sig_token = 0;
7266                         break;
7267                 case METHOD_HEADER_FAT_FORMAT:
7268                         ptr += 2;
7269                         ptr += 2;
7270                         ptr += 4;
7271                         local_var_sig_token = read32 (ptr);
7272                         break;
7273                 default:
7274                         g_assert_not_reached ();
7275                 }
7276         } else
7277                 local_var_sig_token = 0; //FIXME
7278
7279         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7280
7281         ret->init_locals = header->init_locals;
7282         ret->max_stack = header->max_stack;
7283         ret->local_var_sig_token = local_var_sig_token;
7284         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7285         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7286
7287         /* Locals */
7288         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7289         for (i = 0; i < header->num_locals; ++i) {
7290                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7291
7292                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7293                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7294
7295                 MONO_OBJECT_SETREF (info, local_type, rt);
7296
7297                 info->is_pinned = header->locals [i]->pinned;
7298                 info->local_index = i;
7299                 mono_array_setref (ret->locals, i, info);
7300         }
7301
7302         /* Exceptions */
7303         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7304         for (i = 0; i < header->num_clauses; ++i) {
7305                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7306                 MonoExceptionClause *clause = &header->clauses [i];
7307
7308                 info->flags = clause->flags;
7309                 info->try_offset = clause->try_offset;
7310                 info->try_length = clause->try_len;
7311                 info->handler_offset = clause->handler_offset;
7312                 info->handler_length = clause->handler_len;
7313                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7314                         info->filter_offset = clause->data.filter_offset;
7315                 else if (clause->data.catch_class) {
7316                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7317                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7318
7319                         MONO_OBJECT_SETREF (info, catch_type, rt);
7320                 }
7321
7322                 mono_array_setref (ret->clauses, i, info);
7323         }
7324
7325         mono_metadata_free_mh (header);
7326         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7327         return ret;
7328 }
7329
7330 /**
7331  * mono_get_dbnull_object:
7332  * @domain: Domain where the object lives
7333  *
7334  * Returns the System.DBNull.Value singleton object
7335  *
7336  * Used as the value for ParameterInfo.DefaultValue 
7337  */
7338 MonoObject *
7339 mono_get_dbnull_object (MonoDomain *domain)
7340 {
7341         MonoObject *obj;
7342         static MonoClassField *dbnull_value_field = NULL;
7343         
7344         if (!dbnull_value_field) {
7345                 MonoClass *dbnull_klass;
7346                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7347                 mono_class_init (dbnull_klass);
7348                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7349                 g_assert (dbnull_value_field);
7350         }
7351         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7352         g_assert (obj);
7353         return obj;
7354 }
7355
7356 static void
7357 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7358 {
7359         guint32 param_index, i, lastp, crow = 0;
7360         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7361         gint32 idx;
7362
7363         MonoClass *klass = method->klass;
7364         MonoImage *image = klass->image;
7365         MonoMethodSignature *methodsig = mono_method_signature (method);
7366
7367         MonoTableInfo *constt;
7368         MonoTableInfo *methodt;
7369         MonoTableInfo *paramt;
7370
7371         if (!methodsig->param_count)
7372                 return;
7373
7374         mono_class_init (klass);
7375
7376         if (image_is_dynamic (klass->image)) {
7377                 MonoReflectionMethodAux *aux;
7378                 if (method->is_inflated)
7379                         method = ((MonoMethodInflated*)method)->declaring;
7380                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7381                 if (aux && aux->param_defaults) {
7382                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7383                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7384                 }
7385                 return;
7386         }
7387
7388         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7389         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7390         constt = &image->tables [MONO_TABLE_CONSTANT];
7391
7392         idx = mono_method_get_index (method) - 1;
7393         g_assert (idx != -1);
7394
7395         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7396         if (idx + 1 < methodt->rows)
7397                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7398         else
7399                 lastp = paramt->rows + 1;
7400
7401         for (i = param_index; i < lastp; ++i) {
7402                 guint32 paramseq;
7403
7404                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7405                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7406
7407                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7408                         continue;
7409
7410                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7411                 if (!crow) {
7412                         continue;
7413                 }
7414         
7415                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7416                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7417                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7418         }
7419
7420         return;
7421 }
7422
7423 MonoObject *
7424 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7425 {
7426         void *retval;
7427         MonoClass *klass;
7428         MonoObject *object;
7429         MonoType *basetype = type;
7430
7431         if (!blob)
7432                 return NULL;
7433         
7434         klass = mono_class_from_mono_type (type);
7435         if (klass->valuetype) {
7436                 object = mono_object_new (domain, klass);
7437                 retval = ((gchar *) object + sizeof (MonoObject));
7438                 if (klass->enumtype)
7439                         basetype = mono_class_enum_basetype (klass);
7440         } else {
7441                 retval = &object;
7442         }
7443                         
7444         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7445                 return object;
7446         else
7447                 return NULL;
7448 }
7449
7450 static int
7451 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7452         int found_sep;
7453         char *s;
7454         gboolean quoted = FALSE;
7455
7456         memset (assembly, 0, sizeof (MonoAssemblyName));
7457         assembly->culture = "";
7458         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7459
7460         if (*p == '"') {
7461                 quoted = TRUE;
7462                 p++;
7463         }
7464         assembly->name = p;
7465         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7466                 p++;
7467         if (quoted) {
7468                 if (*p != '"')
7469                         return 1;
7470                 *p = 0;
7471                 p++;
7472         }
7473         if (*p != ',')
7474                 return 1;
7475         *p = 0;
7476         /* Remove trailing whitespace */
7477         s = p - 1;
7478         while (*s && g_ascii_isspace (*s))
7479                 *s-- = 0;
7480         p ++;
7481         while (g_ascii_isspace (*p))
7482                 p++;
7483         while (*p) {
7484                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7485                         p += 8;
7486                         assembly->major = strtoul (p, &s, 10);
7487                         if (s == p || *s != '.')
7488                                 return 1;
7489                         p = ++s;
7490                         assembly->minor = strtoul (p, &s, 10);
7491                         if (s == p || *s != '.')
7492                                 return 1;
7493                         p = ++s;
7494                         assembly->build = strtoul (p, &s, 10);
7495                         if (s == p || *s != '.')
7496                                 return 1;
7497                         p = ++s;
7498                         assembly->revision = strtoul (p, &s, 10);
7499                         if (s == p)
7500                                 return 1;
7501                         p = s;
7502                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7503                         p += 8;
7504                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7505                                 assembly->culture = "";
7506                                 p += 7;
7507                         } else {
7508                                 assembly->culture = p;
7509                                 while (*p && *p != ',') {
7510                                         p++;
7511                                 }
7512                         }
7513                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7514                         p += 15;
7515                         if (strncmp (p, "null", 4) == 0) {
7516                                 p += 4;
7517                         } else {
7518                                 int len;
7519                                 gchar *start = p;
7520                                 while (*p && *p != ',') {
7521                                         p++;
7522                                 }
7523                                 len = (p - start + 1);
7524                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7525                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7526                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7527                         }
7528                 } else {
7529                         while (*p && *p != ',')
7530                                 p++;
7531                 }
7532                 found_sep = 0;
7533                 while (g_ascii_isspace (*p) || *p == ',') {
7534                         *p++ = 0;
7535                         found_sep = 1;
7536                         continue;
7537                 }
7538                 /* failed */
7539                 if (!found_sep)
7540                         return 1;
7541         }
7542
7543         return 0;
7544 }
7545
7546 /*
7547  * mono_reflection_parse_type:
7548  * @name: type name
7549  *
7550  * Parse a type name as accepted by the GetType () method and output the info
7551  * extracted in the info structure.
7552  * the name param will be mangled, so, make a copy before passing it to this function.
7553  * The fields in info will be valid until the memory pointed to by name is valid.
7554  *
7555  * See also mono_type_get_name () below.
7556  *
7557  * Returns: 0 on parse error.
7558  */
7559 static int
7560 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7561                              MonoTypeNameParse *info)
7562 {
7563         char *start, *p, *w, *last_point, *startn;
7564         int in_modifiers = 0;
7565         int isbyref = 0, rank = 0, isptr = 0;
7566
7567         start = p = w = name;
7568
7569         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7570         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7571         info->name = info->name_space = NULL;
7572         info->nested = NULL;
7573         info->modifiers = NULL;
7574         info->type_arguments = NULL;
7575
7576         /* last_point separates the namespace from the name */
7577         last_point = NULL;
7578         /* Skips spaces */
7579         while (*p == ' ') p++, start++, w++, name++;
7580
7581         while (*p) {
7582                 switch (*p) {
7583                 case '+':
7584                         *p = 0; /* NULL terminate the name */
7585                         startn = p + 1;
7586                         info->nested = g_list_append (info->nested, startn);
7587                         /* we have parsed the nesting namespace + name */
7588                         if (info->name)
7589                                 break;
7590                         if (last_point) {
7591                                 info->name_space = start;
7592                                 *last_point = 0;
7593                                 info->name = last_point + 1;
7594                         } else {
7595                                 info->name_space = (char *)"";
7596                                 info->name = start;
7597                         }
7598                         break;
7599                 case '.':
7600                         last_point = p;
7601                         break;
7602                 case '\\':
7603                         ++p;
7604                         break;
7605                 case '&':
7606                 case '*':
7607                 case '[':
7608                 case ',':
7609                 case ']':
7610                         in_modifiers = 1;
7611                         break;
7612                 default:
7613                         break;
7614                 }
7615                 if (in_modifiers)
7616                         break;
7617                 // *w++ = *p++;
7618                 p++;
7619         }
7620         
7621         if (!info->name) {
7622                 if (last_point) {
7623                         info->name_space = start;
7624                         *last_point = 0;
7625                         info->name = last_point + 1;
7626                 } else {
7627                         info->name_space = (char *)"";
7628                         info->name = start;
7629                 }
7630         }
7631         while (*p) {
7632                 switch (*p) {
7633                 case '&':
7634                         if (isbyref) /* only one level allowed by the spec */
7635                                 return 0;
7636                         isbyref = 1;
7637                         isptr = 0;
7638                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7639                         *p++ = 0;
7640                         break;
7641                 case '*':
7642                         if (isbyref) /* pointer to ref not okay */
7643                                 return 0;
7644                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7645                         isptr = 1;
7646                         *p++ = 0;
7647                         break;
7648                 case '[':
7649                         if (isbyref) /* array of ref and generic ref are not okay */
7650                                 return 0;
7651                         //Decide if it's an array of a generic argument list
7652                         *p++ = 0;
7653
7654                         if (!*p) //XXX test
7655                                 return 0;
7656                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7657                                 isptr = 0;
7658                                 rank = 1;
7659                                 while (*p) {
7660                                         if (*p == ']')
7661                                                 break;
7662                                         if (*p == ',')
7663                                                 rank++;
7664                                         else if (*p == '*') /* '*' means unknown lower bound */
7665                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7666                                         else
7667                                                 return 0;
7668                                         ++p;
7669                                 }
7670                                 if (*p++ != ']')
7671                                         return 0;
7672                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7673                         } else {
7674                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7675                                         return 0;
7676                                 isptr = 0;
7677                                 info->type_arguments = g_ptr_array_new ();
7678                                 while (*p) {
7679                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7680                                         gboolean fqname = FALSE;
7681
7682                                         g_ptr_array_add (info->type_arguments, subinfo);
7683
7684                                         while (*p == ' ') p++;
7685                                         if (*p == '[') {
7686                                                 p++;
7687                                                 fqname = TRUE;
7688                                         }
7689
7690                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7691                                                 return 0;
7692
7693                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7694                                         if (fqname && (*p != ']')) {
7695                                                 char *aname;
7696
7697                                                 if (*p != ',')
7698                                                         return 0;
7699                                                 *p++ = 0;
7700
7701                                                 aname = p;
7702                                                 while (*p && (*p != ']'))
7703                                                         p++;
7704
7705                                                 if (*p != ']')
7706                                                         return 0;
7707
7708                                                 *p++ = 0;
7709                                                 while (*aname) {
7710                                                         if (g_ascii_isspace (*aname)) {
7711                                                                 ++aname;
7712                                                                 continue;
7713                                                         }
7714                                                         break;
7715                                                 }
7716                                                 if (!*aname ||
7717                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7718                                                         return 0;
7719                                         } else if (fqname && (*p == ']')) {
7720                                                 *p++ = 0;
7721                                         }
7722                                         if (*p == ']') {
7723                                                 *p++ = 0;
7724                                                 break;
7725                                         } else if (!*p) {
7726                                                 return 0;
7727                                         }
7728                                         *p++ = 0;
7729                                 }
7730                         }
7731                         break;
7732                 case ']':
7733                         if (is_recursed)
7734                                 goto end;
7735                         return 0;
7736                 case ',':
7737                         if (is_recursed)
7738                                 goto end;
7739                         *p++ = 0;
7740                         while (*p) {
7741                                 if (g_ascii_isspace (*p)) {
7742                                         ++p;
7743                                         continue;
7744                                 }
7745                                 break;
7746                         }
7747                         if (!*p)
7748                                 return 0; /* missing assembly name */
7749                         if (!assembly_name_to_aname (&info->assembly, p))
7750                                 return 0;
7751                         break;
7752                 default:
7753                         return 0;
7754                 }
7755                 if (info->assembly.name)
7756                         break;
7757         }
7758         // *w = 0; /* terminate class name */
7759  end:
7760         if (!info->name || !*info->name)
7761                 return 0;
7762         if (endptr)
7763                 *endptr = p;
7764         /* add other consistency checks */
7765         return 1;
7766 }
7767
7768
7769 /**
7770  * mono_identifier_unescape_type_name_chars:
7771  * @identifier: the display name of a mono type
7772  *
7773  * Returns:
7774  *  The name in internal form, that is without escaping backslashes.
7775  *
7776  *  The string is modified in place!
7777  */
7778 char*
7779 mono_identifier_unescape_type_name_chars(char* identifier)
7780 {
7781         char *w, *r;
7782         if (!identifier)
7783                 return NULL;
7784         for (w = r = identifier; *r != 0; r++)
7785         {
7786                 char c = *r;
7787                 if (c == '\\') {
7788                         r++;
7789                         if (*r == 0)
7790                                 break;
7791                         c = *r;
7792                 }
7793                 *w = c;
7794                 w++;
7795         }
7796         if (w != r)
7797                 *w = 0;
7798         return identifier;
7799 }
7800
7801 void
7802 mono_identifier_unescape_info (MonoTypeNameParse* info);
7803
7804 static void
7805 unescape_each_type_argument(void* data, void* user_data)
7806 {
7807         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7808         mono_identifier_unescape_info (info);
7809 }
7810
7811 static void
7812 unescape_each_nested_name (void* data, void* user_data)
7813 {
7814         char* nested_name = (char*) data;
7815         mono_identifier_unescape_type_name_chars(nested_name);
7816 }
7817
7818 /**
7819  * mono_identifier_unescape_info:
7820  *
7821  * @info: a parsed display form of an (optionally assembly qualified) full type name.
7822  *
7823  * Returns: nothing.
7824  *
7825  * Destructively updates the info by unescaping the identifiers that
7826  * comprise the type namespace, name, nested types (if any) and
7827  * generic type arguments (if any).
7828  *
7829  * The resulting info has the names in internal form.
7830  *
7831  */
7832 void
7833 mono_identifier_unescape_info (MonoTypeNameParse *info)
7834 {
7835         if (!info)
7836                 return;
7837         mono_identifier_unescape_type_name_chars(info->name_space);
7838         mono_identifier_unescape_type_name_chars(info->name);
7839         // but don't escape info->assembly
7840         if (info->type_arguments)
7841                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7842         if (info->nested)
7843                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7844 }
7845
7846 int
7847 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7848 {
7849         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7850         if (ok) {
7851                 mono_identifier_unescape_info (info);
7852         }
7853         return ok;
7854 }
7855
7856 static MonoType*
7857 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7858 {
7859         gboolean type_resolve = FALSE;
7860         MonoType *type;
7861         MonoImage *rootimage = image;
7862
7863         if (info->assembly.name) {
7864                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7865                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7866                         /* 
7867                          * This could happen in the AOT compiler case when the search hook is not
7868                          * installed.
7869                          */
7870                         assembly = image->assembly;
7871                 if (!assembly) {
7872                         /* then we must load the assembly ourselve - see #60439 */
7873                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7874                         if (!assembly)
7875                                 return NULL;
7876                 }
7877                 image = assembly->image;
7878         } else if (!image) {
7879                 image = mono_defaults.corlib;
7880         }
7881
7882         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7883         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7884                 image = mono_defaults.corlib;
7885                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7886         }
7887
7888         return type;
7889 }
7890
7891 static MonoType*
7892 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7893 {
7894         MonoError error;
7895         MonoClass *klass;
7896         GList *mod;
7897         int modval;
7898         gboolean bounded = FALSE;
7899         
7900         if (!image)
7901                 image = mono_defaults.corlib;
7902
7903         if (!rootimage)
7904                 rootimage = mono_defaults.corlib;
7905
7906         if (ignorecase) {
7907                 MonoError error;
7908                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7909                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7910         } else {
7911                 klass = mono_class_from_name (image, info->name_space, info->name);
7912         }
7913         if (!klass)
7914                 return NULL;
7915         for (mod = info->nested; mod; mod = mod->next) {
7916                 gpointer iter = NULL;
7917                 MonoClass *parent;
7918
7919                 parent = klass;
7920                 mono_class_init (parent);
7921
7922                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7923                         char *lastp;
7924                         char *nested_name, *nested_nspace;
7925                         gboolean match = TRUE;
7926
7927                         lastp = strrchr ((const char *)mod->data, '.');
7928                         if (lastp) {
7929                                 /* Nested classes can have namespaces */
7930                                 int nspace_len;
7931
7932                                 nested_name = g_strdup (lastp + 1);
7933                                 nspace_len = lastp - (char*)mod->data;
7934                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
7935                                 memcpy (nested_nspace, mod->data, nspace_len);
7936                                 nested_nspace [nspace_len] = '\0';
7937
7938                         } else {
7939                                 nested_name = (char *)mod->data;
7940                                 nested_nspace = NULL;
7941                         }
7942
7943                         if (nested_nspace) {
7944                                 if (ignorecase) {
7945                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7946                                                 match = FALSE;
7947                                 } else {
7948                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7949                                                 match = FALSE;
7950                                 }
7951                         }
7952                         if (match) {
7953                                 if (ignorecase) {
7954                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7955                                                 match = FALSE;
7956                                 } else {
7957                                         if (strcmp (klass->name, nested_name) != 0)
7958                                                 match = FALSE;
7959                                 }
7960                         }
7961                         if (lastp) {
7962                                 g_free (nested_name);
7963                                 g_free (nested_nspace);
7964                         }
7965                         if (match)
7966                                 break;
7967                 }
7968
7969                 if (!klass)
7970                         break;
7971         }
7972         if (!klass)
7973                 return NULL;
7974
7975         if (info->type_arguments) {
7976                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7977                 MonoReflectionType *the_type;
7978                 MonoType *instance;
7979                 int i;
7980
7981                 for (i = 0; i < info->type_arguments->len; i++) {
7982                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
7983
7984                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7985                         if (!type_args [i]) {
7986                                 g_free (type_args);
7987                                 return NULL;
7988                         }
7989                 }
7990
7991                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7992                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7993
7994                 instance = mono_reflection_bind_generic_parameters (
7995                         the_type, info->type_arguments->len, type_args);
7996
7997                 g_free (type_args);
7998                 if (!instance)
7999                         return NULL;
8000
8001                 klass = mono_class_from_mono_type (instance);
8002         }
8003
8004         for (mod = info->modifiers; mod; mod = mod->next) {
8005                 modval = GPOINTER_TO_UINT (mod->data);
8006                 if (!modval) { /* byref: must be last modifier */
8007                         return &klass->this_arg;
8008                 } else if (modval == -1) {
8009                         klass = mono_ptr_class_get (&klass->byval_arg);
8010                 } else if (modval == -2) {
8011                         bounded = TRUE;
8012                 } else { /* array rank */
8013                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8014                 }
8015         }
8016
8017         return &klass->byval_arg;
8018 }
8019
8020 /*
8021  * mono_reflection_get_type:
8022  * @image: a metadata context
8023  * @info: type description structure
8024  * @ignorecase: flag for case-insensitive string compares
8025  * @type_resolve: whenever type resolve was already tried
8026  *
8027  * Build a MonoType from the type description in @info.
8028  * 
8029  */
8030
8031 MonoType*
8032 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8033         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8034 }
8035
8036 static MonoType*
8037 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
8038 {
8039         MonoReflectionAssemblyBuilder *abuilder;
8040         MonoType *type;
8041         int i;
8042
8043         g_assert (assembly_is_dynamic (assembly));
8044         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
8045
8046         /* Enumerate all modules */
8047
8048         type = NULL;
8049         if (abuilder->modules) {
8050                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8051                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8052                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
8053                         if (type)
8054                                 break;
8055                 }
8056         }
8057
8058         if (!type && abuilder->loaded_modules) {
8059                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8060                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8061                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
8062                         if (type)
8063                                 break;
8064                 }
8065         }
8066
8067         return type;
8068 }
8069         
8070 MonoType*
8071 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8072 {
8073         MonoType *type;
8074         MonoReflectionAssembly *assembly;
8075         GString *fullName;
8076         GList *mod;
8077
8078         if (image && image_is_dynamic (image))
8079                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8080         else
8081                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8082         if (type)
8083                 return type;
8084         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8085                 return NULL;
8086
8087         if (type_resolve) {
8088                 if (*type_resolve) 
8089                         return NULL;
8090                 else
8091                         *type_resolve = TRUE;
8092         }
8093         
8094         /* Reconstruct the type name */
8095         fullName = g_string_new ("");
8096         if (info->name_space && (info->name_space [0] != '\0'))
8097                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8098         else
8099                 g_string_printf (fullName, "%s", info->name);
8100         for (mod = info->nested; mod; mod = mod->next)
8101                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8102
8103         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8104         if (assembly) {
8105                 if (assembly_is_dynamic (assembly->assembly))
8106                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8107                 else
8108                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8109                                                                                                           info, ignorecase);
8110         }
8111         g_string_free (fullName, TRUE);
8112         return type;
8113 }
8114
8115 void
8116 mono_reflection_free_type_info (MonoTypeNameParse *info)
8117 {
8118         g_list_free (info->modifiers);
8119         g_list_free (info->nested);
8120
8121         if (info->type_arguments) {
8122                 int i;
8123
8124                 for (i = 0; i < info->type_arguments->len; i++) {
8125                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8126
8127                         mono_reflection_free_type_info (subinfo);
8128                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8129                         g_free (subinfo);
8130                 }
8131
8132                 g_ptr_array_free (info->type_arguments, TRUE);
8133         }
8134 }
8135
8136 /*
8137  * mono_reflection_type_from_name:
8138  * @name: type name.
8139  * @image: a metadata context (can be NULL).
8140  *
8141  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8142  * it defaults to get the type from @image or, if @image is NULL or loading
8143  * from it fails, uses corlib.
8144  * 
8145  */
8146 MonoType*
8147 mono_reflection_type_from_name (char *name, MonoImage *image)
8148 {
8149         MonoType *type = NULL;
8150         MonoTypeNameParse info;
8151         char *tmp;
8152
8153         /* Make a copy since parse_type modifies its argument */
8154         tmp = g_strdup (name);
8155         
8156         /*g_print ("requested type %s\n", str);*/
8157         if (mono_reflection_parse_type (tmp, &info)) {
8158                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8159         }
8160
8161         g_free (tmp);
8162         mono_reflection_free_type_info (&info);
8163         return type;
8164 }
8165
8166 /*
8167  * mono_reflection_get_token:
8168  *
8169  *   Return the metadata token of OBJ which should be an object
8170  * representing a metadata element.
8171  */
8172 guint32
8173 mono_reflection_get_token (MonoObject *obj)
8174 {
8175         MonoClass *klass;
8176         guint32 token = 0;
8177
8178         klass = obj->vtable->klass;
8179
8180         if (strcmp (klass->name, "MethodBuilder") == 0) {
8181                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8182
8183                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8184         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8185                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8186
8187                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8188         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8189                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8190
8191                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8192         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8193                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8194                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8195         } else if (strcmp (klass->name, "MonoType") == 0) {
8196                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8197                 MonoClass *mc = mono_class_from_mono_type (type);
8198                 if (!mono_class_init (mc))
8199                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8200
8201                 token = mc->type_token;
8202         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8203                    strcmp (klass->name, "MonoMethod") == 0 ||
8204                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8205                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8206                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8207                 if (m->method->is_inflated) {
8208                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8209                         return inflated->declaring->token;
8210                 } else {
8211                         token = m->method->token;
8212                 }
8213         } else if (strcmp (klass->name, "MonoField") == 0) {
8214                 MonoReflectionField *f = (MonoReflectionField*)obj;
8215
8216                 if (is_field_on_inst (f->field)) {
8217                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8218
8219                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8220                                 int field_index = f->field - dgclass->fields;
8221                                 MonoObject *obj;
8222
8223                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8224                                 obj = dgclass->field_objects [field_index];
8225                                 return mono_reflection_get_token (obj);
8226                         }
8227                 }
8228                 token = mono_class_get_field_token (f->field);
8229         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8230                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8231
8232                 token = mono_class_get_property_token (p->property);
8233         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8234                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8235
8236                 token = mono_class_get_event_token (p->event);
8237         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8238                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8239                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8240                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8241
8242                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8243         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8244                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8245
8246                 token = m->token;
8247         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8248                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8249         } else {
8250                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8251                 MonoException *ex = mono_get_exception_not_implemented (msg);
8252                 g_free (msg);
8253                 mono_raise_exception (ex);
8254         }
8255
8256         return token;
8257 }
8258
8259 static MonoClass*
8260 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8261 {
8262         char *n;
8263         MonoType *t;
8264         int slen = mono_metadata_decode_value (p, &p);
8265
8266         mono_error_init (error);
8267
8268         n = (char *)g_memdup (p, slen + 1);
8269         n [slen] = 0;
8270         t = mono_reflection_type_from_name (n, image);
8271         if (!t) {
8272                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8273                 /* We don't free n, it's consumed by mono_error */
8274                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8275                 return NULL;
8276         }
8277         g_free (n);
8278         p += slen;
8279         *end = p;
8280         return mono_class_from_mono_type (t);
8281 }
8282
8283 static void*
8284 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8285 {
8286         int slen, type = t->type;
8287         MonoClass *tklass = t->data.klass;
8288
8289         mono_error_init (error);
8290
8291 handle_enum:
8292         switch (type) {
8293         case MONO_TYPE_U1:
8294         case MONO_TYPE_I1:
8295         case MONO_TYPE_BOOLEAN: {
8296                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8297                 *bval = *p;
8298                 *end = p + 1;
8299                 return bval;
8300         }
8301         case MONO_TYPE_CHAR:
8302         case MONO_TYPE_U2:
8303         case MONO_TYPE_I2: {
8304                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8305                 *val = read16 (p);
8306                 *end = p + 2;
8307                 return val;
8308         }
8309 #if SIZEOF_VOID_P == 4
8310         case MONO_TYPE_U:
8311         case MONO_TYPE_I:
8312 #endif
8313         case MONO_TYPE_R4:
8314         case MONO_TYPE_U4:
8315         case MONO_TYPE_I4: {
8316                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8317                 *val = read32 (p);
8318                 *end = p + 4;
8319                 return val;
8320         }
8321 #if SIZEOF_VOID_P == 8
8322         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8323         case MONO_TYPE_I:
8324 #endif
8325         case MONO_TYPE_U8:
8326         case MONO_TYPE_I8: {
8327                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8328                 *val = read64 (p);
8329                 *end = p + 8;
8330                 return val;
8331         }
8332         case MONO_TYPE_R8: {
8333                 double *val = (double *)g_malloc (sizeof (double));
8334                 readr8 (p, val);
8335                 *end = p + 8;
8336                 return val;
8337         }
8338         case MONO_TYPE_VALUETYPE:
8339                 if (t->data.klass->enumtype) {
8340                         type = mono_class_enum_basetype (t->data.klass)->type;
8341                         goto handle_enum;
8342                 } else {
8343                         MonoClass *k =  t->data.klass;
8344                         
8345                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8346                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8347                                 *val = read64 (p);
8348                                 *end = p + 8;
8349                                 return val;
8350                         }
8351                 }
8352                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8353                 break;
8354                 
8355         case MONO_TYPE_STRING:
8356                 if (*p == (char)0xFF) {
8357                         *end = p + 1;
8358                         return NULL;
8359                 }
8360                 slen = mono_metadata_decode_value (p, &p);
8361                 *end = p + slen;
8362                 return mono_string_new_len (mono_domain_get (), p, slen);
8363         case MONO_TYPE_CLASS: {
8364                 MonoReflectionType *rt;
8365                 char *n;
8366                 MonoType *t;
8367                 if (*p == (char)0xFF) {
8368                         *end = p + 1;
8369                         return NULL;
8370                 }
8371 handle_type:
8372                 slen = mono_metadata_decode_value (p, &p);
8373                 n = (char *)g_memdup (p, slen + 1);
8374                 n [slen] = 0;
8375                 t = mono_reflection_type_from_name (n, image);
8376                 if (!t) {
8377                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8378                         /* We don't free n, it's consumed by mono_error */
8379                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8380                         return NULL;
8381                 }
8382                 g_free (n);
8383                 *end = p + slen;
8384
8385                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8386                 if (!mono_error_ok (error))
8387                         return NULL;
8388
8389                 return rt;
8390         }
8391         case MONO_TYPE_OBJECT: {
8392                 char subt = *p++;
8393                 MonoObject *obj;
8394                 MonoClass *subc = NULL;
8395                 void *val;
8396
8397                 if (subt == 0x50) {
8398                         goto handle_type;
8399                 } else if (subt == 0x0E) {
8400                         type = MONO_TYPE_STRING;
8401                         goto handle_enum;
8402                 } else if (subt == 0x1D) {
8403                         MonoType simple_type = {{0}};
8404                         int etype = *p;
8405                         p ++;
8406
8407                         type = MONO_TYPE_SZARRAY;
8408                         if (etype == 0x50) {
8409                                 tklass = mono_defaults.systemtype_class;
8410                         } else if (etype == 0x55) {
8411                                 tklass = load_cattr_enum_type (image, p, &p, error);
8412                                 if (!mono_error_ok (error))
8413                                         return NULL;
8414                         } else {
8415                                 if (etype == 0x51)
8416                                         /* See Partition II, Appendix B3 */
8417                                         etype = MONO_TYPE_OBJECT;
8418                                 simple_type.type = (MonoTypeEnum)etype;
8419                                 tklass = mono_class_from_mono_type (&simple_type);
8420                         }
8421                         goto handle_enum;
8422                 } else if (subt == 0x55) {
8423                         char *n;
8424                         MonoType *t;
8425                         slen = mono_metadata_decode_value (p, &p);
8426                         n = (char *)g_memdup (p, slen + 1);
8427                         n [slen] = 0;
8428                         t = mono_reflection_type_from_name (n, image);
8429                         if (!t) {
8430                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8431                                 /* We don't free n, it's consumed by mono_error */
8432                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8433                                 return NULL;
8434                         }
8435                         g_free (n);
8436                         p += slen;
8437                         subc = mono_class_from_mono_type (t);
8438                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8439                         MonoType simple_type = {{0}};
8440                         simple_type.type = (MonoTypeEnum)subt;
8441                         subc = mono_class_from_mono_type (&simple_type);
8442                 } else {
8443                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8444                 }
8445                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8446                 obj = NULL;
8447                 if (mono_error_ok (error)) {
8448                         obj = mono_object_new (mono_domain_get (), subc);
8449                         g_assert (!subc->has_references);
8450                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8451                 }
8452
8453                 g_free (val);
8454                 return obj;
8455         }
8456         case MONO_TYPE_SZARRAY: {
8457                 MonoArray *arr;
8458                 guint32 i, alen, basetype;
8459                 alen = read32 (p);
8460                 p += 4;
8461                 if (alen == 0xffffffff) {
8462                         *end = p;
8463                         return NULL;
8464                 }
8465                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8466                 basetype = tklass->byval_arg.type;
8467                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8468                         basetype = mono_class_enum_basetype (tklass)->type;
8469                 switch (basetype)
8470                 {
8471                         case MONO_TYPE_U1:
8472                         case MONO_TYPE_I1:
8473                         case MONO_TYPE_BOOLEAN:
8474                                 for (i = 0; i < alen; i++) {
8475                                         MonoBoolean val = *p++;
8476                                         mono_array_set (arr, MonoBoolean, i, val);
8477                                 }
8478                                 break;
8479                         case MONO_TYPE_CHAR:
8480                         case MONO_TYPE_U2:
8481                         case MONO_TYPE_I2:
8482                                 for (i = 0; i < alen; i++) {
8483                                         guint16 val = read16 (p);
8484                                         mono_array_set (arr, guint16, i, val);
8485                                         p += 2;
8486                                 }
8487                                 break;
8488                         case MONO_TYPE_R4:
8489                         case MONO_TYPE_U4:
8490                         case MONO_TYPE_I4:
8491                                 for (i = 0; i < alen; i++) {
8492                                         guint32 val = read32 (p);
8493                                         mono_array_set (arr, guint32, i, val);
8494                                         p += 4;
8495                                 }
8496                                 break;
8497                         case MONO_TYPE_R8:
8498                                 for (i = 0; i < alen; i++) {
8499                                         double val;
8500                                         readr8 (p, &val);
8501                                         mono_array_set (arr, double, i, val);
8502                                         p += 8;
8503                                 }
8504                                 break;
8505                         case MONO_TYPE_U8:
8506                         case MONO_TYPE_I8:
8507                                 for (i = 0; i < alen; i++) {
8508                                         guint64 val = read64 (p);
8509                                         mono_array_set (arr, guint64, i, val);
8510                                         p += 8;
8511                                 }
8512                                 break;
8513                         case MONO_TYPE_CLASS:
8514                         case MONO_TYPE_OBJECT:
8515                         case MONO_TYPE_STRING:
8516                         case MONO_TYPE_SZARRAY:
8517                                 for (i = 0; i < alen; i++) {
8518                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8519                                         if (!mono_error_ok (error))
8520                                                 return NULL;
8521                                         mono_array_setref (arr, i, item);
8522                                 }
8523                                 break;
8524                         default:
8525                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8526                 }
8527                 *end=p;
8528                 return arr;
8529         }
8530         default:
8531                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8532         }
8533         return NULL;
8534 }
8535
8536 static MonoObject*
8537 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8538 {
8539         static MonoClass *klass;
8540         static MonoMethod *ctor;
8541         MonoError error;
8542         MonoObject *retval;
8543         void *params [2], *unboxed;
8544
8545         if (!klass)
8546                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8547         if (!ctor)
8548                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8549         
8550         params [0] = mono_type_get_object_checked (mono_domain_get (), t, &error);
8551         mono_error_raise_exception (&error); /* FIXME don't raise here */
8552
8553         params [1] = val;
8554         retval = mono_object_new (mono_domain_get (), klass);
8555         unboxed = mono_object_unbox (retval);
8556         mono_runtime_invoke (ctor, unboxed, params, NULL);
8557
8558         return retval;
8559 }
8560
8561 static MonoObject*
8562 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8563 {
8564         static MonoClass *klass;
8565         static MonoMethod *ctor;
8566         MonoObject *retval;
8567         void *unboxed, *params [2];
8568
8569         if (!klass)
8570                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8571         if (!ctor)
8572                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8573
8574         params [0] = minfo;
8575         params [1] = typedarg;
8576         retval = mono_object_new (mono_domain_get (), klass);
8577         unboxed = mono_object_unbox (retval);
8578         mono_runtime_invoke (ctor, unboxed, params, NULL);
8579
8580         return retval;
8581 }
8582
8583 static gboolean
8584 type_is_reference (MonoType *type)
8585 {
8586         switch (type->type) {
8587         case MONO_TYPE_BOOLEAN:
8588         case MONO_TYPE_CHAR:
8589         case MONO_TYPE_U:
8590         case MONO_TYPE_I:
8591         case MONO_TYPE_U1:
8592         case MONO_TYPE_I1:
8593         case MONO_TYPE_U2:
8594         case MONO_TYPE_I2:
8595         case MONO_TYPE_U4:
8596         case MONO_TYPE_I4:
8597         case MONO_TYPE_U8:
8598         case MONO_TYPE_I8:
8599         case MONO_TYPE_R8:
8600         case MONO_TYPE_R4:
8601         case MONO_TYPE_VALUETYPE:
8602                 return FALSE;
8603         default:
8604                 return TRUE;
8605         }
8606 }
8607
8608 static void
8609 free_param_data (MonoMethodSignature *sig, void **params) {
8610         int i;
8611         for (i = 0; i < sig->param_count; ++i) {
8612                 if (!type_is_reference (sig->params [i]))
8613                         g_free (params [i]);
8614         }
8615 }
8616
8617 /*
8618  * Find the field index in the metadata FieldDef table.
8619  */
8620 static guint32
8621 find_field_index (MonoClass *klass, MonoClassField *field) {
8622         int i;
8623
8624         for (i = 0; i < klass->field.count; ++i) {
8625                 if (field == &klass->fields [i])
8626                         return klass->field.first + 1 + i;
8627         }
8628         return 0;
8629 }
8630
8631 /*
8632  * Find the property index in the metadata Property table.
8633  */
8634 static guint32
8635 find_property_index (MonoClass *klass, MonoProperty *property) {
8636         int i;
8637
8638         for (i = 0; i < klass->ext->property.count; ++i) {
8639                 if (property == &klass->ext->properties [i])
8640                         return klass->ext->property.first + 1 + i;
8641         }
8642         return 0;
8643 }
8644
8645 /*
8646  * Find the event index in the metadata Event table.
8647  */
8648 static guint32
8649 find_event_index (MonoClass *klass, MonoEvent *event) {
8650         int i;
8651
8652         for (i = 0; i < klass->ext->event.count; ++i) {
8653                 if (event == &klass->ext->events [i])
8654                         return klass->ext->event.first + 1 + i;
8655         }
8656         return 0;
8657 }
8658
8659 static MonoObject*
8660 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8661 {
8662         const char *p = (const char*)data;
8663         const char *named;
8664         guint32 i, j, num_named;
8665         MonoObject *attr;
8666         void *params_buf [32];
8667         void **params = NULL;
8668         MonoMethodSignature *sig;
8669         MonoObject *exc = NULL;
8670
8671         mono_error_init (error);
8672
8673         mono_class_init (method->klass);
8674
8675         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8676                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8677                 return NULL;
8678         }
8679
8680         if (len == 0) {
8681                 attr = mono_object_new (mono_domain_get (), method->klass);
8682                 mono_runtime_invoke (method, attr, NULL, NULL);
8683                 return attr;
8684         }
8685
8686         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8687                 return NULL;
8688
8689         /*g_print ("got attr %s\n", method->klass->name);*/
8690
8691         sig = mono_method_signature (method);
8692         if (sig->param_count < 32) {
8693                 params = params_buf;
8694                 memset (params, 0, sizeof (void*) * sig->param_count);
8695         } else {
8696                 /* Allocate using GC so it gets GC tracking */
8697                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8698         }
8699
8700         /* skip prolog */
8701         p += 2;
8702         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8703                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8704                 if (!mono_error_ok (error))
8705                         goto fail;
8706         }
8707
8708         named = p;
8709         attr = mono_object_new (mono_domain_get (), method->klass);
8710
8711         mono_runtime_invoke (method, attr, params, &exc);
8712         if (exc)
8713                 goto fail;
8714         num_named = read16 (named);
8715         named += 2;
8716         for (j = 0; j < num_named; j++) {
8717                 gint name_len;
8718                 char *name, named_type, data_type;
8719                 named_type = *named++;
8720                 data_type = *named++; /* type of data */
8721                 if (data_type == MONO_TYPE_SZARRAY)
8722                         data_type = *named++;
8723                 if (data_type == MONO_TYPE_ENUM) {
8724                         gint type_len;
8725                         char *type_name;
8726                         type_len = mono_metadata_decode_blob_size (named, &named);
8727                         type_name = (char *)g_malloc (type_len + 1);
8728                         memcpy (type_name, named, type_len);
8729                         type_name [type_len] = 0;
8730                         named += type_len;
8731                         /* FIXME: lookup the type and check type consistency */
8732                         g_free (type_name);
8733                 }
8734                 name_len = mono_metadata_decode_blob_size (named, &named);
8735                 name = (char *)g_malloc (name_len + 1);
8736                 memcpy (name, named, name_len);
8737                 name [name_len] = 0;
8738                 named += name_len;
8739                 if (named_type == 0x53) {
8740                         MonoClassField *field;
8741                         void *val;
8742
8743                         /* how this fail is a blackbox */
8744                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8745                         if (!field) {
8746                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8747                                 g_free (name);
8748                                 goto fail;
8749                         }
8750
8751                         val = load_cattr_value (image, field->type, named, &named, error);
8752                         if (!mono_error_ok (error)) {
8753                                 g_free (name);
8754                                 if (!type_is_reference (field->type))
8755                                         g_free (val);
8756                                 goto fail;
8757                         }
8758
8759                         mono_field_set_value (attr, field, val);
8760                         if (!type_is_reference (field->type))
8761                                 g_free (val);
8762                 } else if (named_type == 0x54) {
8763                         MonoProperty *prop;
8764                         void *pparams [1];
8765                         MonoType *prop_type;
8766
8767                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8768
8769                         if (!prop) {
8770                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8771                                 g_free (name);
8772                                 goto fail;
8773                         }
8774
8775                         if (!prop->set) {
8776                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8777                                 g_free (name);
8778                                 goto fail;
8779                         }
8780
8781                         /* can we have more that 1 arg in a custom attr named property? */
8782                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8783                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8784
8785                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8786                         if (!mono_error_ok (error)) {
8787                                 g_free (name);
8788                                 if (!type_is_reference (prop_type))
8789                                         g_free (pparams [0]);
8790                                 goto fail;
8791                         }
8792
8793
8794                         mono_property_set_value (prop, attr, pparams, NULL);
8795                         if (!type_is_reference (prop_type))
8796                                 g_free (pparams [0]);
8797                 }
8798                 g_free (name);
8799         }
8800
8801         free_param_data (method->signature, params);
8802         if (params != params_buf)
8803                 mono_gc_free_fixed (params);
8804
8805         return attr;
8806
8807 fail:
8808         free_param_data (method->signature, params);
8809         if (params != params_buf)
8810                 mono_gc_free_fixed (params);
8811         if (exc)
8812                 mono_raise_exception ((MonoException*)exc);
8813         return NULL;
8814 }
8815         
8816 /*
8817  * mono_reflection_create_custom_attr_data_args:
8818  *
8819  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8820  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8821  * NAMED_ARG_INFO will contain information about the named arguments.
8822  */
8823 void
8824 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)
8825 {
8826         MonoArray *typedargs, *namedargs;
8827         MonoClass *attrklass;
8828         MonoDomain *domain;
8829         const char *p = (const char*)data;
8830         const char *named;
8831         guint32 i, j, num_named;
8832         CattrNamedArg *arginfo = NULL;
8833
8834         *typed_args = NULL;
8835         *named_args = NULL;
8836         *named_arg_info = NULL;
8837
8838         mono_error_init (error);
8839
8840         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8841                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8842                 return;
8843         }
8844
8845         mono_class_init (method->klass);
8846         
8847         domain = mono_domain_get ();
8848
8849         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8850                 return;
8851
8852         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8853         
8854         /* skip prolog */
8855         p += 2;
8856         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8857                 MonoObject *obj;
8858                 void *val;
8859
8860                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8861                 if (!mono_error_ok (error)) {
8862                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8863                                 g_free (val);
8864                         return;
8865                 }
8866
8867                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8868                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8869                 mono_array_setref (typedargs, i, obj);
8870
8871                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8872                         g_free (val);
8873         }
8874
8875         named = p;
8876         num_named = read16 (named);
8877         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8878         named += 2;
8879         attrklass = method->klass;
8880
8881         arginfo = g_new0 (CattrNamedArg, num_named);
8882         *named_arg_info = arginfo;
8883
8884         for (j = 0; j < num_named; j++) {
8885                 gint name_len;
8886                 char *name, named_type, data_type;
8887                 named_type = *named++;
8888                 data_type = *named++; /* type of data */
8889                 if (data_type == MONO_TYPE_SZARRAY)
8890                         data_type = *named++;
8891                 if (data_type == MONO_TYPE_ENUM) {
8892                         gint type_len;
8893                         char *type_name;
8894                         type_len = mono_metadata_decode_blob_size (named, &named);
8895                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8896                                 goto fail;
8897
8898                         type_name = (char *)g_malloc (type_len + 1);
8899                         memcpy (type_name, named, type_len);
8900                         type_name [type_len] = 0;
8901                         named += type_len;
8902                         /* FIXME: lookup the type and check type consistency */
8903                         g_free (type_name);
8904                 }
8905                 name_len = mono_metadata_decode_blob_size (named, &named);
8906                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8907                         goto fail;
8908                 name = (char *)g_malloc (name_len + 1);
8909                 memcpy (name, named, name_len);
8910                 name [name_len] = 0;
8911                 named += name_len;
8912                 if (named_type == 0x53) {
8913                         MonoObject *obj;
8914                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8915                         void *val;
8916
8917                         if (!field) {
8918                                 g_free (name);
8919                                 goto fail;
8920                         }
8921
8922                         arginfo [j].type = field->type;
8923                         arginfo [j].field = field;
8924
8925                         val = load_cattr_value (image, field->type, named, &named, error);
8926                         if (!mono_error_ok (error)) {
8927                                 if (!type_is_reference (field->type))
8928                                         g_free (val);
8929                                 g_free (name);
8930                                 return;
8931                         }
8932
8933                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8934                         mono_array_setref (namedargs, j, obj);
8935                         if (!type_is_reference (field->type))
8936                                 g_free (val);
8937                 } else if (named_type == 0x54) {
8938                         MonoObject *obj;
8939                         MonoType *prop_type;
8940                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8941                         void *val;
8942
8943                         if (!prop || !prop->set) {
8944                                 g_free (name);
8945                                 goto fail;
8946                         }
8947
8948                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8949                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8950
8951                         arginfo [j].type = prop_type;
8952                         arginfo [j].prop = prop;
8953
8954                         val = load_cattr_value (image, prop_type, named, &named, error);
8955                         if (!mono_error_ok (error)) {
8956                                 if (!type_is_reference (prop_type))
8957                                         g_free (val);
8958                                 g_free (name);
8959                                 return;
8960                         }
8961
8962                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8963                         mono_array_setref (namedargs, j, obj);
8964                         if (!type_is_reference (prop_type))
8965                                 g_free (val);
8966                 }
8967                 g_free (name);
8968         }
8969
8970         *typed_args = typedargs;
8971         *named_args = namedargs;
8972         return;
8973 fail:
8974         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8975         g_free (arginfo);
8976         *named_arg_info = NULL;
8977 }
8978
8979 void
8980 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8981 {
8982         MonoDomain *domain;
8983         MonoArray *typedargs, *namedargs;
8984         MonoImage *image;
8985         MonoMethod *method;
8986         CattrNamedArg *arginfo = NULL;
8987         MonoError error;
8988         int i;
8989
8990         *ctor_args = NULL;
8991         *named_args = NULL;
8992
8993         if (len == 0)
8994                 return;
8995
8996         image = assembly->assembly->image;
8997         method = ref_method->method;
8998         domain = mono_object_domain (ref_method);
8999
9000         if (!mono_class_init (method->klass))
9001                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9002
9003         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9004         if (!mono_error_ok (&error))
9005                 mono_error_raise_exception (&error);
9006         if (mono_loader_get_last_error ())
9007                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
9008
9009         if (!typedargs || !namedargs) {
9010                 g_free (arginfo);
9011                 return;
9012         }
9013
9014         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9015                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9016                 MonoObject *typedarg;
9017
9018                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
9019                 mono_array_setref (typedargs, i, typedarg);
9020         }
9021
9022         for (i = 0; i < mono_array_length (namedargs); ++i) {
9023                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9024                 MonoObject *typedarg, *namedarg, *minfo;
9025
9026                 if (arginfo [i].prop)
9027                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
9028                 else
9029                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
9030
9031                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
9032                 namedarg = create_cattr_named_arg (minfo, typedarg);
9033
9034                 mono_array_setref (namedargs, i, namedarg);
9035         }
9036
9037         *ctor_args = typedargs;
9038         *named_args = namedargs;
9039         g_free (arginfo);
9040 }
9041
9042 static MonoObject*
9043 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
9044 {
9045         static MonoMethod *ctor;
9046         MonoDomain *domain;
9047         MonoObject *attr;
9048         void *params [4];
9049
9050         g_assert (image->assembly);
9051
9052         if (!ctor)
9053                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9054
9055         domain = mono_domain_get ();
9056         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
9057         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
9058         params [1] = mono_assembly_get_object (domain, image->assembly);
9059         params [2] = (gpointer)&cattr->data;
9060         params [3] = &cattr->data_size;
9061         mono_runtime_invoke (ctor, attr, params, NULL);
9062         return attr;
9063 }
9064
9065 static MonoArray*
9066 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9067 {
9068         MonoArray *result;
9069         MonoObject *attr;
9070         int i, n;
9071
9072         mono_error_init (error);
9073
9074         n = 0;
9075         for (i = 0; i < cinfo->num_attrs; ++i) {
9076                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9077                         n ++;
9078         }
9079
9080         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9081         n = 0;
9082         for (i = 0; i < cinfo->num_attrs; ++i) {
9083                 if (!cinfo->attrs [i].ctor)
9084                         /* The cattr type is not finished yet */
9085                         /* We should include the type name but cinfo doesn't contain it */
9086                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9087                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9088                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9089                         if (!mono_error_ok (error))
9090                                 return result;
9091                         mono_array_setref (result, n, attr);
9092                         n ++;
9093                 }
9094         }
9095         return result;
9096 }
9097
9098 MonoArray*
9099 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9100 {
9101         MonoError error;
9102         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9103         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9104
9105         return result;
9106 }
9107
9108 static MonoArray*
9109 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9110 {
9111         MonoArray *result;
9112         MonoObject *attr;
9113         int i;
9114         
9115         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9116         for (i = 0; i < cinfo->num_attrs; ++i) {
9117                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9118                 mono_array_setref (result, i, attr);
9119         }
9120         return result;
9121 }
9122
9123 /**
9124  * mono_custom_attrs_from_index:
9125  *
9126  * Returns: NULL if no attributes are found or if a loading error occurs.
9127  */
9128 MonoCustomAttrInfo*
9129 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9130 {
9131         guint32 mtoken, i, len;
9132         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9133         MonoTableInfo *ca;
9134         MonoCustomAttrInfo *ainfo;
9135         GList *tmp, *list = NULL;
9136         const char *data;
9137         MonoCustomAttrEntry* attr;
9138
9139         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9140
9141         i = mono_metadata_custom_attrs_from_index (image, idx);
9142         if (!i)
9143                 return NULL;
9144         i --;
9145         while (i < ca->rows) {
9146                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9147                         break;
9148                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9149                 ++i;
9150         }
9151         len = g_list_length (list);
9152         if (!len)
9153                 return NULL;
9154         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9155         ainfo->num_attrs = len;
9156         ainfo->image = image;
9157         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9158                 MonoError error;
9159                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9160                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9161                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9162                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9163                         mtoken |= MONO_TOKEN_METHOD_DEF;
9164                         break;
9165                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9166                         mtoken |= MONO_TOKEN_MEMBER_REF;
9167                         break;
9168                 default:
9169                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9170                         break;
9171                 }
9172                 attr = &ainfo->attrs [i - 1];
9173                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9174                 if (!attr->ctor) {
9175                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9176                         mono_loader_set_error_from_mono_error (&error);
9177                         g_list_free (list);
9178                         g_free (ainfo);
9179                         return NULL;
9180                 }
9181
9182                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9183                         /*FIXME raising an exception here doesn't make any sense*/
9184                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9185                         g_list_free (list);
9186                         g_free (ainfo);
9187                         return NULL;
9188                 }
9189                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9190                 attr->data_size = mono_metadata_decode_value (data, &data);
9191                 attr->data = (guchar*)data;
9192         }
9193         g_list_free (list);
9194
9195         return ainfo;
9196 }
9197
9198 MonoCustomAttrInfo*
9199 mono_custom_attrs_from_method (MonoMethod *method)
9200 {
9201         guint32 idx;
9202
9203         /*
9204          * An instantiated method has the same cattrs as the generic method definition.
9205          *
9206          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9207          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9208          */
9209         if (method->is_inflated)
9210                 method = ((MonoMethodInflated *) method)->declaring;
9211         
9212         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9213                 return lookup_custom_attr (method->klass->image, method);
9214
9215         if (!method->token)
9216                 /* Synthetic methods */
9217                 return NULL;
9218
9219         idx = mono_method_get_index (method);
9220         idx <<= MONO_CUSTOM_ATTR_BITS;
9221         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9222         return mono_custom_attrs_from_index (method->klass->image, idx);
9223 }
9224
9225 MonoCustomAttrInfo*
9226 mono_custom_attrs_from_class (MonoClass *klass)
9227 {
9228         guint32 idx;
9229
9230         if (klass->generic_class)
9231                 klass = klass->generic_class->container_class;
9232
9233         if (image_is_dynamic (klass->image))
9234                 return lookup_custom_attr (klass->image, klass);
9235
9236         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9237                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9238                 idx <<= MONO_CUSTOM_ATTR_BITS;
9239                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9240         } else {
9241                 idx = mono_metadata_token_index (klass->type_token);
9242                 idx <<= MONO_CUSTOM_ATTR_BITS;
9243                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9244         }
9245         return mono_custom_attrs_from_index (klass->image, idx);
9246 }
9247
9248 MonoCustomAttrInfo*
9249 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9250 {
9251         guint32 idx;
9252         
9253         if (image_is_dynamic (assembly->image))
9254                 return lookup_custom_attr (assembly->image, assembly);
9255         idx = 1; /* there is only one assembly */
9256         idx <<= MONO_CUSTOM_ATTR_BITS;
9257         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9258         return mono_custom_attrs_from_index (assembly->image, idx);
9259 }
9260
9261 static MonoCustomAttrInfo*
9262 mono_custom_attrs_from_module (MonoImage *image)
9263 {
9264         guint32 idx;
9265         
9266         if (image_is_dynamic (image))
9267                 return lookup_custom_attr (image, image);
9268         idx = 1; /* there is only one module */
9269         idx <<= MONO_CUSTOM_ATTR_BITS;
9270         idx |= MONO_CUSTOM_ATTR_MODULE;
9271         return mono_custom_attrs_from_index (image, idx);
9272 }
9273
9274 MonoCustomAttrInfo*
9275 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9276 {
9277         guint32 idx;
9278         
9279         if (image_is_dynamic (klass->image)) {
9280                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9281                 return lookup_custom_attr (klass->image, property);
9282         }
9283         idx = find_property_index (klass, property);
9284         idx <<= MONO_CUSTOM_ATTR_BITS;
9285         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9286         return mono_custom_attrs_from_index (klass->image, idx);
9287 }
9288
9289 MonoCustomAttrInfo*
9290 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9291 {
9292         guint32 idx;
9293         
9294         if (image_is_dynamic (klass->image)) {
9295                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9296                 return lookup_custom_attr (klass->image, event);
9297         }
9298         idx = find_event_index (klass, event);
9299         idx <<= MONO_CUSTOM_ATTR_BITS;
9300         idx |= MONO_CUSTOM_ATTR_EVENT;
9301         return mono_custom_attrs_from_index (klass->image, idx);
9302 }
9303
9304 MonoCustomAttrInfo*
9305 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9306 {
9307         guint32 idx;
9308         if (image_is_dynamic (klass->image)) {
9309                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9310                 return lookup_custom_attr (klass->image, field);
9311         }
9312         idx = find_field_index (klass, field);
9313         idx <<= MONO_CUSTOM_ATTR_BITS;
9314         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9315         return mono_custom_attrs_from_index (klass->image, idx);
9316 }
9317
9318 /**
9319  * mono_custom_attrs_from_param:
9320  * @method: handle to the method that we want to retrieve custom parameter information from
9321  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9322  *
9323  * The result must be released with mono_custom_attrs_free().
9324  *
9325  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9326  */
9327 MonoCustomAttrInfo*
9328 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9329 {
9330         MonoTableInfo *ca;
9331         guint32 i, idx, method_index;
9332         guint32 param_list, param_last, param_pos, found;
9333         MonoImage *image;
9334         MonoReflectionMethodAux *aux;
9335
9336         /*
9337          * An instantiated method has the same cattrs as the generic method definition.
9338          *
9339          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9340          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9341          */
9342         if (method->is_inflated)
9343                 method = ((MonoMethodInflated *) method)->declaring;
9344
9345         if (image_is_dynamic (method->klass->image)) {
9346                 MonoCustomAttrInfo *res, *ainfo;
9347                 int size;
9348
9349                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9350                 if (!aux || !aux->param_cattr)
9351                         return NULL;
9352
9353                 /* Need to copy since it will be freed later */
9354                 ainfo = aux->param_cattr [param];
9355                 if (!ainfo)
9356                         return NULL;
9357                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9358                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9359                 memcpy (res, ainfo, size);
9360                 return res;
9361         }
9362
9363         image = method->klass->image;
9364         method_index = mono_method_get_index (method);
9365         if (!method_index)
9366                 return NULL;
9367         ca = &image->tables [MONO_TABLE_METHOD];
9368
9369         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9370         if (method_index == ca->rows) {
9371                 ca = &image->tables [MONO_TABLE_PARAM];
9372                 param_last = ca->rows + 1;
9373         } else {
9374                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9375                 ca = &image->tables [MONO_TABLE_PARAM];
9376         }
9377         found = FALSE;
9378         for (i = param_list; i < param_last; ++i) {
9379                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9380                 if (param_pos == param) {
9381                         found = TRUE;
9382                         break;
9383                 }
9384         }
9385         if (!found)
9386                 return NULL;
9387         idx = i;
9388         idx <<= MONO_CUSTOM_ATTR_BITS;
9389         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9390         return mono_custom_attrs_from_index (image, idx);
9391 }
9392
9393 gboolean
9394 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9395 {
9396         int i;
9397         MonoClass *klass;
9398         for (i = 0; i < ainfo->num_attrs; ++i) {
9399                 klass = ainfo->attrs [i].ctor->klass;
9400                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9401                         return TRUE;
9402         }
9403         return FALSE;
9404 }
9405
9406 MonoObject*
9407 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9408 {
9409         MonoError error;
9410         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9411         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9412         return res;
9413 }
9414
9415 MonoObject*
9416 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9417 {
9418         int i, attr_index;
9419         MonoClass *klass;
9420         MonoArray *attrs;
9421
9422         mono_error_init (error);
9423
9424         attr_index = -1;
9425         for (i = 0; i < ainfo->num_attrs; ++i) {
9426                 klass = ainfo->attrs [i].ctor->klass;
9427                 if (mono_class_has_parent (klass, attr_klass)) {
9428                         attr_index = i;
9429                         break;
9430                 }
9431         }
9432         if (attr_index == -1)
9433                 return NULL;
9434
9435         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9436         if (!mono_error_ok (error))
9437                 return NULL;
9438         return mono_array_get (attrs, MonoObject*, attr_index);
9439 }
9440
9441 /*
9442  * mono_reflection_get_custom_attrs_info:
9443  * @obj: a reflection object handle
9444  *
9445  * Return the custom attribute info for attributes defined for the
9446  * reflection handle @obj. The objects.
9447  *
9448  * FIXME this function leaks like a sieve for SRE objects.
9449  */
9450 MonoCustomAttrInfo*
9451 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9452 {
9453         MonoClass *klass;
9454         MonoCustomAttrInfo *cinfo = NULL;
9455         
9456         klass = obj->vtable->klass;
9457         if (klass == mono_defaults.monotype_class) {
9458                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9459                 klass = mono_class_from_mono_type (type);
9460                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9461                 cinfo = mono_custom_attrs_from_class (klass);
9462         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9463                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9464                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9465         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9466                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9467                 cinfo = mono_custom_attrs_from_module (module->image);
9468         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9469                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9470                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9471         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9472                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9473                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9474         } else if (strcmp ("MonoField", klass->name) == 0) {
9475                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9476                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9477         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9478                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9479                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9480         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9481                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9482                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9483         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9484                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9485                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9486                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9487                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9488                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9489                 } else if (is_sr_mono_property (member_class)) {
9490                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9491                         MonoMethod *method;
9492                         if (!(method = prop->property->get))
9493                                 method = prop->property->set;
9494                         g_assert (method);
9495
9496                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9497                 } 
9498 #ifndef DISABLE_REFLECTION_EMIT
9499                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9500                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9501                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9502                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9503                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9504                         MonoMethod *method = NULL;
9505                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9506                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9507                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9508                                 method = ((MonoReflectionMethod *)c->cb)->method;
9509                         else
9510                                 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));
9511
9512                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9513                 } 
9514 #endif
9515                 else {
9516                         char *type_name = mono_type_get_full_name (member_class);
9517                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9518                         MonoException *ex = mono_get_exception_not_supported  (msg);
9519                         g_free (type_name);
9520                         g_free (msg);
9521                         mono_raise_exception (ex);
9522                 }
9523         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9524                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9525                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9526         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9527                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9528                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9529         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9530                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9531                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9532         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9533                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9534                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9535         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9536                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9537                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9538         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9539                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9540                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9541         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9542                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9543                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9544         } else { /* handle other types here... */
9545                 g_error ("get custom attrs not yet supported for %s", klass->name);
9546         }
9547
9548         return cinfo;
9549 }
9550
9551 /*
9552  * mono_reflection_get_custom_attrs_by_type:
9553  * @obj: a reflection object handle
9554  *
9555  * Return an array with all the custom attributes defined of the
9556  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9557  * of that type are returned. The objects are fully build. Return NULL if a loading error
9558  * occurs.
9559  */
9560 MonoArray*
9561 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9562 {
9563         MonoArray *result;
9564         MonoCustomAttrInfo *cinfo;
9565
9566         mono_error_init (error);
9567
9568         cinfo = mono_reflection_get_custom_attrs_info (obj);
9569         if (cinfo) {
9570                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9571                 if (!cinfo->cached)
9572                         mono_custom_attrs_free (cinfo);
9573         } else {
9574                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9575                 if (mono_loader_get_last_error ())
9576                         return NULL;
9577                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9578         }
9579
9580         return result;
9581 }
9582
9583 /*
9584  * mono_reflection_get_custom_attrs:
9585  * @obj: a reflection object handle
9586  *
9587  * Return an array with all the custom attributes defined of the
9588  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9589  * occurs.
9590  */
9591 MonoArray*
9592 mono_reflection_get_custom_attrs (MonoObject *obj)
9593 {
9594         MonoError error;
9595
9596         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9597 }
9598
9599 /*
9600  * mono_reflection_get_custom_attrs_data:
9601  * @obj: a reflection obj handle
9602  *
9603  * Returns an array of System.Reflection.CustomAttributeData,
9604  * which include information about attributes reflected on
9605  * types loaded using the Reflection Only methods
9606  */
9607 MonoArray*
9608 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9609 {
9610         MonoArray *result;
9611         MonoCustomAttrInfo *cinfo;
9612
9613         cinfo = mono_reflection_get_custom_attrs_info (obj);
9614         if (cinfo) {
9615                 result = mono_custom_attrs_data_construct (cinfo);
9616                 if (!cinfo->cached)
9617                         mono_custom_attrs_free (cinfo);
9618         } else
9619                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9620
9621         return result;
9622 }
9623
9624 static MonoReflectionType*
9625 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9626 {
9627         static MonoMethod *method_get_underlying_system_type = NULL;
9628         MonoMethod *usertype_method;
9629
9630         if (!method_get_underlying_system_type)
9631                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9632         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9633         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9634 }
9635
9636
9637 static gboolean
9638 is_corlib_type (MonoClass *klass)
9639 {
9640         return klass->image == mono_defaults.corlib;
9641 }
9642
9643 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9644         static MonoClass *cached_class; \
9645         if (cached_class) \
9646                 return cached_class == _class; \
9647         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9648                 cached_class = _class; \
9649                 return TRUE; \
9650         } \
9651         return FALSE; \
9652 } while (0) \
9653
9654
9655 #ifndef DISABLE_REFLECTION_EMIT
9656 static gboolean
9657 is_sre_array (MonoClass *klass)
9658 {
9659         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9660 }
9661
9662 static gboolean
9663 is_sre_byref (MonoClass *klass)
9664 {
9665         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9666 }
9667
9668 static gboolean
9669 is_sre_pointer (MonoClass *klass)
9670 {
9671         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9672 }
9673
9674 static gboolean
9675 is_sre_generic_instance (MonoClass *klass)
9676 {
9677         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9678 }
9679
9680 static gboolean
9681 is_sre_type_builder (MonoClass *klass)
9682 {
9683         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9684 }
9685
9686 static gboolean
9687 is_sre_method_builder (MonoClass *klass)
9688 {
9689         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9690 }
9691
9692 static gboolean
9693 is_sre_ctor_builder (MonoClass *klass)
9694 {
9695         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9696 }
9697
9698 static gboolean
9699 is_sre_field_builder (MonoClass *klass)
9700 {
9701         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9702 }
9703
9704 static gboolean
9705 is_sre_method_on_tb_inst (MonoClass *klass)
9706 {
9707         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9708 }
9709
9710 static gboolean
9711 is_sre_ctor_on_tb_inst (MonoClass *klass)
9712 {
9713         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9714 }
9715
9716 MonoType*
9717 mono_reflection_type_get_handle (MonoReflectionType* ref)
9718 {
9719         MonoClass *klass;
9720         if (!ref)
9721                 return NULL;
9722         if (ref->type)
9723                 return ref->type;
9724
9725         if (is_usertype (ref)) {
9726                 ref = mono_reflection_type_get_underlying_system_type (ref);
9727                 if (ref == NULL || is_usertype (ref))
9728                         return NULL;
9729                 if (ref->type)
9730                         return ref->type;
9731         }
9732
9733         klass = mono_object_class (ref);
9734
9735         if (is_sre_array (klass)) {
9736                 MonoType *res;
9737                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9738                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9739                 g_assert (base);
9740                 if (sre_array->rank == 0) //single dimentional array
9741                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9742                 else
9743                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9744                 sre_array->type.type = res;
9745                 return res;
9746         } else if (is_sre_byref (klass)) {
9747                 MonoType *res;
9748                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9749                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9750                 g_assert (base);
9751                 res = &mono_class_from_mono_type (base)->this_arg;
9752                 sre_byref->type.type = res;
9753                 return res;
9754         } else if (is_sre_pointer (klass)) {
9755                 MonoType *res;
9756                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9757                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9758                 g_assert (base);
9759                 res = &mono_ptr_class_get (base)->byval_arg;
9760                 sre_pointer->type.type = res;
9761                 return res;
9762         } else if (is_sre_generic_instance (klass)) {
9763                 MonoType *res, **types;
9764                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9765                 int i, count;
9766
9767                 count = mono_array_length (gclass->type_arguments);
9768                 types = g_new0 (MonoType*, count);
9769                 for (i = 0; i < count; ++i) {
9770                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9771                         types [i] = mono_reflection_type_get_handle (t);
9772                         if (!types[i]) {
9773                                 g_free (types);
9774                                 return NULL;
9775                         }
9776                 }
9777
9778                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9779                 g_free (types);
9780                 g_assert (res);
9781                 gclass->type.type = res;
9782                 return res;
9783         }
9784
9785         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9786         return NULL;
9787 }
9788
9789
9790
9791 void
9792 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9793 {
9794         mono_reflection_type_get_handle (type);
9795 }
9796
9797 void
9798 mono_reflection_register_with_runtime (MonoReflectionType *type)
9799 {
9800         MonoType *res = mono_reflection_type_get_handle (type);
9801         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9802         MonoClass *klass;
9803
9804         if (!res)
9805                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9806
9807         klass = mono_class_from_mono_type (res);
9808
9809         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
9810         mono_domain_lock (domain);
9811
9812         if (!image_is_dynamic (klass->image)) {
9813                 mono_class_setup_supertypes (klass);
9814         } else {
9815                 if (!domain->type_hash)
9816                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9817                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9818                 mono_g_hash_table_insert (domain->type_hash, res, type);
9819         }
9820         mono_domain_unlock (domain);
9821         mono_loader_unlock ();
9822 }
9823
9824 /**
9825  * LOCKING: Assumes the loader lock is held.
9826  */
9827 static MonoMethodSignature*
9828 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9829         MonoMethodSignature *sig;
9830         int count, i;
9831
9832         count = parameters? mono_array_length (parameters): 0;
9833
9834         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9835         sig->param_count = count;
9836         sig->sentinelpos = -1; /* FIXME */
9837         for (i = 0; i < count; ++i)
9838                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9839         return sig;
9840 }
9841
9842 /**
9843  * LOCKING: Assumes the loader lock is held.
9844  */
9845 static MonoMethodSignature*
9846 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9847         MonoMethodSignature *sig;
9848
9849         sig = parameters_to_signature (image, ctor->parameters);
9850         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9851         sig->ret = &mono_defaults.void_class->byval_arg;
9852         return sig;
9853 }
9854
9855 /**
9856  * LOCKING: Assumes the loader lock is held.
9857  */
9858 static MonoMethodSignature*
9859 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9860         MonoMethodSignature *sig;
9861
9862         sig = parameters_to_signature (image, method->parameters);
9863         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9864         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9865         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9866         return sig;
9867 }
9868
9869 static MonoMethodSignature*
9870 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9871         MonoMethodSignature *sig;
9872
9873         sig = parameters_to_signature (NULL, method->parameters);
9874         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9875         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9876         sig->generic_param_count = 0;
9877         return sig;
9878 }
9879
9880 static void
9881 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9882 {
9883         MonoClass *klass = mono_object_class (prop);
9884         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9885                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9886                 *name = mono_string_to_utf8 (pb->name);
9887                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9888         } else {
9889                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9890                 *name = g_strdup (p->property->name);
9891                 if (p->property->get)
9892                         *type = mono_method_signature (p->property->get)->ret;
9893                 else
9894                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9895         }
9896 }
9897
9898 static void
9899 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9900 {
9901         MonoClass *klass = mono_object_class (field);
9902         if (strcmp (klass->name, "FieldBuilder") == 0) {
9903                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9904                 *name = mono_string_to_utf8 (fb->name);
9905                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9906         } else {
9907                 MonoReflectionField *f = (MonoReflectionField *)field;
9908                 *name = g_strdup (mono_field_get_name (f->field));
9909                 *type = f->field->type;
9910         }
9911 }
9912
9913 #else /* DISABLE_REFLECTION_EMIT */
9914
9915 void
9916 mono_reflection_register_with_runtime (MonoReflectionType *type)
9917 {
9918         /* This is empty */
9919 }
9920
9921 static gboolean
9922 is_sre_type_builder (MonoClass *klass)
9923 {
9924         return FALSE;
9925 }
9926
9927 static gboolean
9928 is_sre_generic_instance (MonoClass *klass)
9929 {
9930         return FALSE;
9931 }
9932
9933 static void
9934 init_type_builder_generics (MonoObject *type)
9935 {
9936 }
9937
9938 #endif /* !DISABLE_REFLECTION_EMIT */
9939
9940
9941 static gboolean
9942 is_sr_mono_field (MonoClass *klass)
9943 {
9944         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9945 }
9946
9947 static gboolean
9948 is_sr_mono_property (MonoClass *klass)
9949 {
9950         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9951 }
9952
9953 static gboolean
9954 is_sr_mono_method (MonoClass *klass)
9955 {
9956         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9957 }
9958
9959 static gboolean
9960 is_sr_mono_cmethod (MonoClass *klass)
9961 {
9962         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9963 }
9964
9965 static gboolean
9966 is_sr_mono_generic_method (MonoClass *klass)
9967 {
9968         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9969 }
9970
9971 static gboolean
9972 is_sr_mono_generic_cmethod (MonoClass *klass)
9973 {
9974         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9975 }
9976
9977 gboolean
9978 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9979 {
9980         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9981 }
9982
9983 static gboolean
9984 is_usertype (MonoReflectionType *ref)
9985 {
9986         MonoClass *klass = mono_object_class (ref);
9987         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9988 }
9989
9990 static MonoReflectionType*
9991 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
9992 {
9993         mono_error_init (error);
9994         if (!type || type->type)
9995                 return type;
9996
9997         if (is_usertype (type)) {
9998                 type = mono_reflection_type_get_underlying_system_type (type);
9999                 if (is_usertype (type)) {
10000                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10001                         return NULL;
10002                 }
10003         }
10004
10005         return type;
10006 }
10007 /*
10008  * Encode a value in a custom attribute stream of bytes.
10009  * The value to encode is either supplied as an object in argument val
10010  * (valuetypes are boxed), or as a pointer to the data in the
10011  * argument argval.
10012  * @type represents the type of the value
10013  * @buffer is the start of the buffer
10014  * @p the current position in the buffer
10015  * @buflen contains the size of the buffer and is used to return the new buffer size
10016  * if this needs to be realloced.
10017  * @retbuffer and @retp return the start and the position of the buffer
10018  */
10019 static void
10020 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10021 {
10022         MonoTypeEnum simple_type;
10023         
10024         if ((p-buffer) + 10 >= *buflen) {
10025                 char *newbuf;
10026                 *buflen *= 2;
10027                 newbuf = (char *)g_realloc (buffer, *buflen);
10028                 p = newbuf + (p-buffer);
10029                 buffer = newbuf;
10030         }
10031         if (!argval)
10032                 argval = ((char*)arg + sizeof (MonoObject));
10033         simple_type = type->type;
10034 handle_enum:
10035         switch (simple_type) {
10036         case MONO_TYPE_BOOLEAN:
10037         case MONO_TYPE_U1:
10038         case MONO_TYPE_I1:
10039                 *p++ = *argval;
10040                 break;
10041         case MONO_TYPE_CHAR:
10042         case MONO_TYPE_U2:
10043         case MONO_TYPE_I2:
10044                 swap_with_size (p, argval, 2, 1);
10045                 p += 2;
10046                 break;
10047         case MONO_TYPE_U4:
10048         case MONO_TYPE_I4:
10049         case MONO_TYPE_R4:
10050                 swap_with_size (p, argval, 4, 1);
10051                 p += 4;
10052                 break;
10053         case MONO_TYPE_R8:
10054                 swap_with_size (p, argval, 8, 1);
10055                 p += 8;
10056                 break;
10057         case MONO_TYPE_U8:
10058         case MONO_TYPE_I8:
10059                 swap_with_size (p, argval, 8, 1);
10060                 p += 8;
10061                 break;
10062         case MONO_TYPE_VALUETYPE:
10063                 if (type->data.klass->enumtype) {
10064                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10065                         goto handle_enum;
10066                 } else {
10067                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10068                 }
10069                 break;
10070         case MONO_TYPE_STRING: {
10071                 char *str;
10072                 guint32 slen;
10073                 if (!arg) {
10074                         *p++ = 0xFF;
10075                         break;
10076                 }
10077                 str = mono_string_to_utf8 ((MonoString*)arg);
10078                 slen = strlen (str);
10079                 if ((p-buffer) + 10 + slen >= *buflen) {
10080                         char *newbuf;
10081                         *buflen *= 2;
10082                         *buflen += slen;
10083                         newbuf = (char *)g_realloc (buffer, *buflen);
10084                         p = newbuf + (p-buffer);
10085                         buffer = newbuf;
10086                 }
10087                 mono_metadata_encode_value (slen, p, &p);
10088                 memcpy (p, str, slen);
10089                 p += slen;
10090                 g_free (str);
10091                 break;
10092         }
10093         case MONO_TYPE_CLASS: {
10094                 char *str;
10095                 guint32 slen;
10096                 if (!arg) {
10097                         *p++ = 0xFF;
10098                         break;
10099                 }
10100 handle_type:
10101                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10102                 slen = strlen (str);
10103                 if ((p-buffer) + 10 + slen >= *buflen) {
10104                         char *newbuf;
10105                         *buflen *= 2;
10106                         *buflen += slen;
10107                         newbuf = (char *)g_realloc (buffer, *buflen);
10108                         p = newbuf + (p-buffer);
10109                         buffer = newbuf;
10110                 }
10111                 mono_metadata_encode_value (slen, p, &p);
10112                 memcpy (p, str, slen);
10113                 p += slen;
10114                 g_free (str);
10115                 break;
10116         }
10117         case MONO_TYPE_SZARRAY: {
10118                 int len, i;
10119                 MonoClass *eclass, *arg_eclass;
10120
10121                 if (!arg) {
10122                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10123                         break;
10124                 }
10125                 len = mono_array_length ((MonoArray*)arg);
10126                 *p++ = len & 0xff;
10127                 *p++ = (len >> 8) & 0xff;
10128                 *p++ = (len >> 16) & 0xff;
10129                 *p++ = (len >> 24) & 0xff;
10130                 *retp = p;
10131                 *retbuffer = buffer;
10132                 eclass = type->data.klass;
10133                 arg_eclass = mono_object_class (arg)->element_class;
10134
10135                 if (!eclass) {
10136                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10137                         eclass = mono_defaults.object_class;
10138                 }
10139                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10140                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10141                         int elsize = mono_class_array_element_size (arg_eclass);
10142                         for (i = 0; i < len; ++i) {
10143                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10144                                 elptr += elsize;
10145                         }
10146                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10147                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10148                         int elsize = mono_class_array_element_size (eclass);
10149                         for (i = 0; i < len; ++i) {
10150                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10151                                 elptr += elsize;
10152                         }
10153                 } else {
10154                         for (i = 0; i < len; ++i) {
10155                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10156                         }
10157                 }
10158                 break;
10159         }
10160         case MONO_TYPE_OBJECT: {
10161                 MonoClass *klass;
10162                 char *str;
10163                 guint32 slen;
10164
10165                 /*
10166                  * The parameter type is 'object' but the type of the actual
10167                  * argument is not. So we have to add type information to the blob
10168                  * too. This is completely undocumented in the spec.
10169                  */
10170
10171                 if (arg == NULL) {
10172                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10173                         *p++ = 0xFF;
10174                         break;
10175                 }
10176                 
10177                 klass = mono_object_class (arg);
10178
10179                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10180                         *p++ = 0x50;
10181                         goto handle_type;
10182                 } else if (klass->enumtype) {
10183                         *p++ = 0x55;
10184                 } else if (klass == mono_defaults.string_class) {
10185                         simple_type = MONO_TYPE_STRING;
10186                         *p++ = 0x0E;
10187                         goto handle_enum;
10188                 } else if (klass->rank == 1) {
10189                         *p++ = 0x1D;
10190                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10191                                 /* See Partition II, Appendix B3 */
10192                                 *p++ = 0x51;
10193                         else
10194                                 *p++ = klass->element_class->byval_arg.type;
10195                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10196                         break;
10197                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10198                         *p++ = simple_type = klass->byval_arg.type;
10199                         goto handle_enum;
10200                 } else {
10201                         g_error ("unhandled type in custom attr");
10202                 }
10203                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10204                 slen = strlen (str);
10205                 if ((p-buffer) + 10 + slen >= *buflen) {
10206                         char *newbuf;
10207                         *buflen *= 2;
10208                         *buflen += slen;
10209                         newbuf = (char *)g_realloc (buffer, *buflen);
10210                         p = newbuf + (p-buffer);
10211                         buffer = newbuf;
10212                 }
10213                 mono_metadata_encode_value (slen, p, &p);
10214                 memcpy (p, str, slen);
10215                 p += slen;
10216                 g_free (str);
10217                 simple_type = mono_class_enum_basetype (klass)->type;
10218                 goto handle_enum;
10219         }
10220         default:
10221                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10222         }
10223         *retp = p;
10224         *retbuffer = buffer;
10225 }
10226
10227 static void
10228 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10229 {
10230         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10231                 char *str = type_get_qualified_name (type, NULL);
10232                 int slen = strlen (str);
10233
10234                 *p++ = 0x55;
10235                 /*
10236                  * This seems to be optional...
10237                  * *p++ = 0x80;
10238                  */
10239                 mono_metadata_encode_value (slen, p, &p);
10240                 memcpy (p, str, slen);
10241                 p += slen;
10242                 g_free (str);
10243         } else if (type->type == MONO_TYPE_OBJECT) {
10244                 *p++ = 0x51;
10245         } else if (type->type == MONO_TYPE_CLASS) {
10246                 /* it should be a type: encode_cattr_value () has the check */
10247                 *p++ = 0x50;
10248         } else {
10249                 mono_metadata_encode_value (type->type, p, &p);
10250                 if (type->type == MONO_TYPE_SZARRAY)
10251                         /* See the examples in Partition VI, Annex B */
10252                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10253         }
10254
10255         *retp = p;
10256 }
10257
10258 #ifndef DISABLE_REFLECTION_EMIT
10259 static void
10260 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10261 {
10262         int len;
10263         /* Preallocate a large enough buffer */
10264         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10265                 char *str = type_get_qualified_name (type, NULL);
10266                 len = strlen (str);
10267                 g_free (str);
10268         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10269                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10270                 len = strlen (str);
10271                 g_free (str);
10272         } else {
10273                 len = 0;
10274         }
10275         len += strlen (name);
10276
10277         if ((p-buffer) + 20 + len >= *buflen) {
10278                 char *newbuf;
10279                 *buflen *= 2;
10280                 *buflen += len;
10281                 newbuf = (char *)g_realloc (buffer, *buflen);
10282                 p = newbuf + (p-buffer);
10283                 buffer = newbuf;
10284         }
10285
10286         encode_field_or_prop_type (type, p, &p);
10287
10288         len = strlen (name);
10289         mono_metadata_encode_value (len, p, &p);
10290         memcpy (p, name, len);
10291         p += len;
10292         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10293         *retp = p;
10294         *retbuffer = buffer;
10295 }
10296
10297 /*
10298  * mono_reflection_get_custom_attrs_blob:
10299  * @ctor: custom attribute constructor
10300  * @ctorArgs: arguments o the constructor
10301  * @properties:
10302  * @propValues:
10303  * @fields:
10304  * @fieldValues:
10305  * 
10306  * Creates the blob of data that needs to be saved in the metadata and that represents
10307  * the custom attributed described by @ctor, @ctorArgs etc.
10308  * Returns: a Byte array representing the blob of data.
10309  */
10310 MonoArray*
10311 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10312 {
10313         MonoArray *result;
10314         MonoMethodSignature *sig;
10315         MonoObject *arg;
10316         char *buffer, *p;
10317         guint32 buflen, i;
10318
10319         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10320                 /* sig is freed later so allocate it in the heap */
10321                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10322         } else {
10323                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10324         }
10325
10326         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10327         buflen = 256;
10328         p = buffer = (char *)g_malloc (buflen);
10329         /* write the prolog */
10330         *p++ = 1;
10331         *p++ = 0;
10332         for (i = 0; i < sig->param_count; ++i) {
10333                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10334                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10335         }
10336         i = 0;
10337         if (properties)
10338                 i += mono_array_length (properties);
10339         if (fields)
10340                 i += mono_array_length (fields);
10341         *p++ = i & 0xff;
10342         *p++ = (i >> 8) & 0xff;
10343         if (properties) {
10344                 MonoObject *prop;
10345                 for (i = 0; i < mono_array_length (properties); ++i) {
10346                         MonoType *ptype;
10347                         char *pname;
10348
10349                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10350                         get_prop_name_and_type (prop, &pname, &ptype);
10351                         *p++ = 0x54; /* PROPERTY signature */
10352                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10353                         g_free (pname);
10354                 }
10355         }
10356
10357         if (fields) {
10358                 MonoObject *field;
10359                 for (i = 0; i < mono_array_length (fields); ++i) {
10360                         MonoType *ftype;
10361                         char *fname;
10362
10363                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10364                         get_field_name_and_type (field, &fname, &ftype);
10365                         *p++ = 0x53; /* FIELD signature */
10366                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10367                         g_free (fname);
10368                 }
10369         }
10370
10371         g_assert (p - buffer <= buflen);
10372         buflen = p - buffer;
10373         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10374         p = mono_array_addr (result, char, 0);
10375         memcpy (p, buffer, buflen);
10376         g_free (buffer);
10377         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10378                 g_free (sig);
10379         return result;
10380 }
10381
10382 /*
10383  * mono_reflection_setup_internal_class:
10384  * @tb: a TypeBuilder object
10385  *
10386  * Creates a MonoClass that represents the TypeBuilder.
10387  * This is a trick that lets us simplify a lot of reflection code
10388  * (and will allow us to support Build and Run assemblies easier).
10389  */
10390 void
10391 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10392 {
10393         MonoError error;
10394         MonoClass *klass, *parent;
10395
10396         RESOLVE_TYPE (tb->parent, &error);
10397         mono_error_raise_exception (&error); /* FIXME don't raise here */
10398
10399         mono_loader_lock ();
10400
10401         if (tb->parent) {
10402                 /* check so we can compile corlib correctly */
10403                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10404                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10405                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10406                 } else {
10407                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10408                 }
10409         } else {
10410                 parent = NULL;
10411         }
10412         
10413         /* the type has already being created: it means we just have to change the parent */
10414         if (tb->type.type) {
10415                 klass = mono_class_from_mono_type (tb->type.type);
10416                 klass->parent = NULL;
10417                 /* fool mono_class_setup_parent */
10418                 klass->supertypes = NULL;
10419                 mono_class_setup_parent (klass, parent);
10420                 mono_class_setup_mono_type (klass);
10421                 mono_loader_unlock ();
10422                 return;
10423         }
10424
10425         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10426
10427         klass->image = &tb->module->dynamic_image->image;
10428
10429         klass->inited = 1; /* we lie to the runtime */
10430         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10431         if (!mono_error_ok (&error))
10432                 goto failure;
10433         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10434         if (!mono_error_ok (&error))
10435                 goto failure;
10436         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10437         klass->flags = tb->attrs;
10438         
10439         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10440
10441         klass->element_class = klass;
10442
10443         if (mono_class_get_ref_info (klass) == NULL) {
10444
10445                 mono_class_set_ref_info (klass, tb);
10446
10447                 /* Put into cache so mono_class_get_checked () will find it.
10448                 Skip nested types as those should not be available on the global scope. */
10449                 if (!tb->nesting_type)
10450                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10451
10452                 /*
10453                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10454                 by performing a mono_class_get which does the full resolution.
10455
10456                 Working around this semantics would require us to write a lot of code for no clear advantage.
10457                 */
10458                 mono_image_append_class_to_reflection_info_set (klass);
10459         } else {
10460                 g_assert (mono_class_get_ref_info (klass) == tb);
10461         }
10462
10463         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10464
10465         if (parent != NULL) {
10466                 mono_class_setup_parent (klass, parent);
10467         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10468                 const char *old_n = klass->name;
10469                 /* trick to get relative numbering right when compiling corlib */
10470                 klass->name = "BuildingObject";
10471                 mono_class_setup_parent (klass, mono_defaults.object_class);
10472                 klass->name = old_n;
10473         }
10474
10475         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10476                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10477                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10478                 klass->instance_size = sizeof (MonoObject);
10479                 klass->size_inited = 1;
10480                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10481         }
10482
10483         mono_class_setup_mono_type (klass);
10484
10485         mono_class_setup_supertypes (klass);
10486
10487         /*
10488          * FIXME: handle interfaces.
10489          */
10490
10491         tb->type.type = &klass->byval_arg;
10492
10493         if (tb->nesting_type) {
10494                 g_assert (tb->nesting_type->type);
10495                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10496         }
10497
10498         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10499
10500         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10501         
10502         mono_loader_unlock ();
10503         return;
10504
10505 failure:
10506         mono_loader_unlock ();
10507         mono_error_raise_exception (&error);
10508 }
10509
10510 /*
10511  * mono_reflection_setup_generic_class:
10512  * @tb: a TypeBuilder object
10513  *
10514  * Setup the generic class before adding the first generic parameter.
10515  */
10516 void
10517 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10518 {
10519 }
10520
10521 /*
10522  * mono_reflection_create_generic_class:
10523  * @tb: a TypeBuilder object
10524  *
10525  * Creates the generic class after all generic parameters have been added.
10526  */
10527 void
10528 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10529 {
10530         MonoClass *klass;
10531         int count, i;
10532
10533         klass = mono_class_from_mono_type (tb->type.type);
10534
10535         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10536
10537         if (klass->generic_container || (count == 0))
10538                 return;
10539
10540         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10541
10542         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10543
10544         klass->generic_container->owner.klass = klass;
10545         klass->generic_container->type_argc = count;
10546         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10547
10548         klass->is_generic = 1;
10549
10550         for (i = 0; i < count; i++) {
10551                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10552                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10553                 klass->generic_container->type_params [i] = *param;
10554                 /*Make sure we are a diferent type instance */
10555                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10556                 klass->generic_container->type_params [i].info.pklass = NULL;
10557                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10558
10559                 g_assert (klass->generic_container->type_params [i].param.owner);
10560         }
10561
10562         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10563 }
10564
10565 /*
10566  * mono_reflection_create_internal_class:
10567  * @tb: a TypeBuilder object
10568  *
10569  * Actually create the MonoClass that is associated with the TypeBuilder.
10570  */
10571 void
10572 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10573 {
10574         MonoClass *klass;
10575
10576         klass = mono_class_from_mono_type (tb->type.type);
10577
10578         mono_loader_lock ();
10579         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10580                 MonoReflectionFieldBuilder *fb;
10581                 MonoClass *ec;
10582                 MonoType *enum_basetype;
10583
10584                 g_assert (tb->fields != NULL);
10585                 g_assert (mono_array_length (tb->fields) >= 1);
10586
10587                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10588
10589                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10590                         mono_loader_unlock ();
10591                         return;
10592                 }
10593
10594                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10595                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10596                 if (!klass->element_class)
10597                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10598
10599                 /*
10600                  * get the element_class from the current corlib.
10601                  */
10602                 ec = default_class_from_mono_type (enum_basetype);
10603                 klass->instance_size = ec->instance_size;
10604                 klass->size_inited = 1;
10605                 /* 
10606                  * this is almost safe to do with enums and it's needed to be able
10607                  * to create objects of the enum type (for use in SetConstant).
10608                  */
10609                 /* FIXME: Does this mean enums can't have method overrides ? */
10610                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10611         }
10612         mono_loader_unlock ();
10613 }
10614
10615 static MonoMarshalSpec*
10616 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10617                                                                 MonoReflectionMarshal *minfo)
10618 {
10619         MonoMarshalSpec *res;
10620
10621         res = image_g_new0 (image, MonoMarshalSpec, 1);
10622         res->native = (MonoMarshalNative)minfo->type;
10623
10624         switch (minfo->type) {
10625         case MONO_NATIVE_LPARRAY:
10626                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10627                 if (minfo->has_size) {
10628                         res->data.array_data.param_num = minfo->param_num;
10629                         res->data.array_data.num_elem = minfo->count;
10630                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10631                 }
10632                 else {
10633                         res->data.array_data.param_num = -1;
10634                         res->data.array_data.num_elem = -1;
10635                         res->data.array_data.elem_mult = -1;
10636                 }
10637                 break;
10638
10639         case MONO_NATIVE_BYVALTSTR:
10640         case MONO_NATIVE_BYVALARRAY:
10641                 res->data.array_data.num_elem = minfo->count;
10642                 break;
10643
10644         case MONO_NATIVE_CUSTOM:
10645                 if (minfo->marshaltyperef)
10646                         res->data.custom_data.custom_name =
10647                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10648                 if (minfo->mcookie)
10649                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10650                 break;
10651
10652         default:
10653                 break;
10654         }
10655
10656         return res;
10657 }
10658 #endif /* !DISABLE_REFLECTION_EMIT */
10659
10660 MonoReflectionMarshalAsAttribute*
10661 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10662                                                                                    MonoMarshalSpec *spec)
10663 {
10664         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10665         MonoError error;
10666         MonoReflectionType *rt;
10667         MonoReflectionMarshalAsAttribute *minfo;
10668         MonoType *mtype;
10669
10670         if (!System_Reflection_Emit_MarshalAsAttribute) {
10671                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10672                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10673                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10674         }
10675
10676         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10677         minfo->utype = spec->native;
10678
10679         switch (minfo->utype) {
10680         case MONO_NATIVE_LPARRAY:
10681                 minfo->array_subtype = spec->data.array_data.elem_type;
10682                 minfo->size_const = spec->data.array_data.num_elem;
10683                 if (spec->data.array_data.param_num != -1)
10684                         minfo->size_param_index = spec->data.array_data.param_num;
10685                 break;
10686
10687         case MONO_NATIVE_BYVALTSTR:
10688         case MONO_NATIVE_BYVALARRAY:
10689                 minfo->size_const = spec->data.array_data.num_elem;
10690                 break;
10691
10692         case MONO_NATIVE_CUSTOM:
10693                 if (spec->data.custom_data.custom_name) {
10694                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10695                         if (mtype) {
10696                                 rt = mono_type_get_object_checked (domain, mtype, &error);
10697                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10698
10699                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
10700                         }
10701
10702                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10703                 }
10704                 if (spec->data.custom_data.cookie)
10705                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10706                 break;
10707
10708         default:
10709                 break;
10710         }
10711
10712         return minfo;
10713 }
10714
10715 #ifndef DISABLE_REFLECTION_EMIT
10716 static MonoMethod*
10717 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10718                                          ReflectionMethodBuilder *rmb,
10719                                          MonoMethodSignature *sig)
10720 {
10721         MonoError error;
10722         MonoMethod *m;
10723         MonoMethodWrapper *wrapperm;
10724         MonoMarshalSpec **specs;
10725         MonoReflectionMethodAux *method_aux;
10726         MonoImage *image;
10727         gboolean dynamic;
10728         int i;
10729
10730         mono_error_init (&error);
10731         /*
10732          * Methods created using a MethodBuilder should have their memory allocated
10733          * inside the image mempool, while dynamic methods should have their memory
10734          * malloc'd.
10735          */
10736         dynamic = rmb->refs != NULL;
10737         image = dynamic ? NULL : klass->image;
10738
10739         if (!dynamic)
10740                 g_assert (!klass->generic_class);
10741
10742         mono_loader_lock ();
10743
10744         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10745                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10746                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10747         else
10748                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10749
10750         wrapperm = (MonoMethodWrapper*)m;
10751
10752         m->dynamic = dynamic;
10753         m->slot = -1;
10754         m->flags = rmb->attrs;
10755         m->iflags = rmb->iattrs;
10756         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10757         m->klass = klass;
10758         m->signature = sig;
10759         m->sre_method = TRUE;
10760         m->skip_visibility = rmb->skip_visibility;
10761         if (rmb->table_idx)
10762                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10763
10764         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10765                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10766                         m->string_ctor = 1;
10767
10768                 m->signature->pinvoke = 1;
10769         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10770                 m->signature->pinvoke = 1;
10771
10772                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10773
10774                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10775                 g_assert (mono_error_ok (&error));
10776                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10777                 g_assert (mono_error_ok (&error));
10778                 
10779                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10780
10781                 if (image_is_dynamic (klass->image))
10782                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10783
10784                 mono_loader_unlock ();
10785
10786                 return m;
10787         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10788                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10789                 MonoMethodHeader *header;
10790                 guint32 code_size;
10791                 gint32 max_stack, i;
10792                 gint32 num_locals = 0;
10793                 gint32 num_clauses = 0;
10794                 guint8 *code;
10795
10796                 if (rmb->ilgen) {
10797                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10798                         code_size = rmb->ilgen->code_len;
10799                         max_stack = rmb->ilgen->max_stack;
10800                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10801                         if (rmb->ilgen->ex_handlers)
10802                                 num_clauses = method_count_clauses (rmb->ilgen);
10803                 } else {
10804                         if (rmb->code) {
10805                                 code = mono_array_addr (rmb->code, guint8, 0);
10806                                 code_size = mono_array_length (rmb->code);
10807                                 /* we probably need to run a verifier on the code... */
10808                                 max_stack = 8; 
10809                         }
10810                         else {
10811                                 code = NULL;
10812                                 code_size = 0;
10813                                 max_stack = 8;
10814                         }
10815                 }
10816
10817                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10818                 header->code_size = code_size;
10819                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10820                 memcpy ((char*)header->code, code, code_size);
10821                 header->max_stack = max_stack;
10822                 header->init_locals = rmb->init_locals;
10823                 header->num_locals = num_locals;
10824
10825                 for (i = 0; i < num_locals; ++i) {
10826                         MonoReflectionLocalBuilder *lb = 
10827                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10828
10829                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10830                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10831                 }
10832
10833                 header->num_clauses = num_clauses;
10834                 if (num_clauses) {
10835                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10836                                  rmb->ilgen, num_clauses);
10837                 }
10838
10839                 wrapperm->header = header;
10840         }
10841
10842         if (rmb->generic_params) {
10843                 int count = mono_array_length (rmb->generic_params);
10844                 MonoGenericContainer *container = rmb->generic_container;
10845
10846                 g_assert (container);
10847
10848                 container->type_argc = count;
10849                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10850                 container->owner.method = m;
10851                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10852
10853                 m->is_generic = TRUE;
10854                 mono_method_set_generic_container (m, container);
10855
10856                 for (i = 0; i < count; i++) {
10857                         MonoReflectionGenericParam *gp =
10858                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10859                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10860                         container->type_params [i] = *param;
10861                 }
10862
10863                 /*
10864                  * The method signature might have pointers to generic parameters that belong to other methods.
10865                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10866                  * generic parameters.
10867                  */
10868                 for (i = 0; i < m->signature->param_count; ++i) {
10869                         MonoType *t = m->signature->params [i];
10870                         if (t->type == MONO_TYPE_MVAR) {
10871                                 MonoGenericParam *gparam =  t->data.generic_param;
10872                                 if (gparam->num < count) {
10873                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10874                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10875                                 }
10876
10877                         }
10878                 }
10879
10880                 if (klass->generic_container) {
10881                         container->parent = klass->generic_container;
10882                         container->context.class_inst = klass->generic_container->context.class_inst;
10883                 }
10884                 container->context.method_inst = mono_get_shared_generic_inst (container);
10885         }
10886
10887         if (rmb->refs) {
10888                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10889                 int i;
10890                 void **data;
10891
10892                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10893
10894                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10895                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10896                 for (i = 0; i < rmb->nrefs; ++i)
10897                         data [i + 1] = rmb->refs [i];
10898         }
10899
10900         method_aux = NULL;
10901
10902         /* Parameter info */
10903         if (rmb->pinfo) {
10904                 if (!method_aux)
10905                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10906                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10907                 for (i = 0; i <= m->signature->param_count; ++i) {
10908                         MonoReflectionParamBuilder *pb;
10909                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10910                                 if ((i > 0) && (pb->attrs)) {
10911                                         /* Make a copy since it might point to a shared type structure */
10912                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10913                                         m->signature->params [i - 1]->attrs = pb->attrs;
10914                                 }
10915
10916                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10917                                         MonoDynamicImage *assembly;
10918                                         guint32 idx, len;
10919                                         MonoTypeEnum def_type;
10920                                         char *p;
10921                                         const char *p2;
10922
10923                                         if (!method_aux->param_defaults) {
10924                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10925                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10926                                         }
10927                                         assembly = (MonoDynamicImage*)klass->image;
10928                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10929                                         /* Copy the data from the blob since it might get realloc-ed */
10930                                         p = assembly->blob.data + idx;
10931                                         len = mono_metadata_decode_blob_size (p, &p2);
10932                                         len += p2 - p;
10933                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10934                                         method_aux->param_default_types [i] = def_type;
10935                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10936                                 }
10937
10938                                 if (pb->name) {
10939                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10940                                         g_assert (mono_error_ok (&error));
10941                                 }
10942                                 if (pb->cattrs) {
10943                                         if (!method_aux->param_cattr)
10944                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10945                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10946                                 }
10947                         }
10948                 }
10949         }
10950
10951         /* Parameter marshalling */
10952         specs = NULL;
10953         if (rmb->pinfo)         
10954                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10955                         MonoReflectionParamBuilder *pb;
10956                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10957                                 if (pb->marshal_info) {
10958                                         if (specs == NULL)
10959                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10960                                         specs [pb->position] = 
10961                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10962                                 }
10963                         }
10964                 }
10965         if (specs != NULL) {
10966                 if (!method_aux)
10967                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10968                 method_aux->param_marshall = specs;
10969         }
10970
10971         if (image_is_dynamic (klass->image) && method_aux)
10972                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10973
10974         mono_loader_unlock ();
10975
10976         return m;
10977 }       
10978
10979 static MonoMethod*
10980 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10981 {
10982         ReflectionMethodBuilder rmb;
10983         MonoMethodSignature *sig;
10984
10985         mono_loader_lock ();
10986         sig = ctor_builder_to_signature (klass->image, mb);
10987         mono_loader_unlock ();
10988
10989         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10990
10991         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10992         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10993
10994         /* If we are in a generic class, we might be called multiple times from inflate_method */
10995         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10996                 /* ilgen is no longer needed */
10997                 mb->ilgen = NULL;
10998         }
10999
11000         return mb->mhandle;
11001 }
11002
11003 static MonoMethod*
11004 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
11005 {
11006         ReflectionMethodBuilder rmb;
11007         MonoMethodSignature *sig;
11008
11009         mono_loader_lock ();
11010         sig = method_builder_to_signature (klass->image, mb);
11011         mono_loader_unlock ();
11012
11013         reflection_methodbuilder_from_method_builder (&rmb, mb);
11014
11015         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11016         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11017
11018         /* If we are in a generic class, we might be called multiple times from inflate_method */
11019         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11020                 /* ilgen is no longer needed */
11021                 mb->ilgen = NULL;
11022         }
11023         return mb->mhandle;
11024 }
11025
11026 static MonoClassField*
11027 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11028 {
11029         MonoClassField *field;
11030         MonoType *custom;
11031         MonoError error;
11032
11033         field = g_new0 (MonoClassField, 1);
11034
11035         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11036         g_assert (mono_error_ok (&error));
11037         if (fb->attrs || fb->modreq || fb->modopt) {
11038                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11039                 field->type->attrs = fb->attrs;
11040
11041                 g_assert (image_is_dynamic (klass->image));
11042                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11043                 g_free (field->type);
11044                 field->type = mono_metadata_type_dup (klass->image, custom);
11045                 g_free (custom);
11046         } else {
11047                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11048         }
11049         if (fb->offset != -1)
11050                 field->offset = fb->offset;
11051         field->parent = klass;
11052         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11053
11054         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11055
11056         return field;
11057 }
11058 #endif
11059
11060 MonoType*
11061 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11062 {
11063         MonoClass *klass;
11064         MonoReflectionTypeBuilder *tb = NULL;
11065         gboolean is_dynamic = FALSE;
11066         MonoClass *geninst;
11067
11068         mono_loader_lock ();
11069
11070         if (is_sre_type_builder (mono_object_class (type))) {
11071                 tb = (MonoReflectionTypeBuilder *) type;
11072
11073                 is_dynamic = TRUE;
11074         } else if (is_sre_generic_instance (mono_object_class (type))) {
11075                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11076                 MonoReflectionType *gtd = rgi->generic_type;
11077
11078                 if (is_sre_type_builder (mono_object_class (gtd))) {
11079                         tb = (MonoReflectionTypeBuilder *)gtd;
11080                         is_dynamic = TRUE;
11081                 }
11082         }
11083
11084         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11085         if (tb && tb->generic_container)
11086                 mono_reflection_create_generic_class (tb);
11087
11088         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11089         if (!klass->generic_container) {
11090                 mono_loader_unlock ();
11091                 return NULL;
11092         }
11093
11094         if (klass->wastypebuilder) {
11095                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11096
11097                 is_dynamic = TRUE;
11098         }
11099
11100         mono_loader_unlock ();
11101
11102         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11103
11104         return &geninst->byval_arg;
11105 }
11106
11107 MonoClass*
11108 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11109 {
11110         MonoGenericClass *gclass;
11111         MonoGenericInst *inst;
11112
11113         g_assert (klass->generic_container);
11114
11115         inst = mono_metadata_get_generic_inst (type_argc, types);
11116         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11117
11118         return mono_generic_class_get_class (gclass);
11119 }
11120
11121 MonoReflectionMethod*
11122 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11123 {
11124         MonoError error;
11125         MonoClass *klass;
11126         MonoMethod *method, *inflated;
11127         MonoMethodInflated *imethod;
11128         MonoGenericContext tmp_context;
11129         MonoGenericInst *ginst;
11130         MonoType **type_argv;
11131         int count, i;
11132
11133         /*FIXME but this no longer should happen*/
11134         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11135 #ifndef DISABLE_REFLECTION_EMIT
11136                 MonoReflectionMethodBuilder *mb = NULL;
11137                 MonoReflectionTypeBuilder *tb;
11138                 MonoClass *klass;
11139
11140                 mb = (MonoReflectionMethodBuilder *) rmethod;
11141                 tb = (MonoReflectionTypeBuilder *) mb->type;
11142                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11143
11144                 method = methodbuilder_to_mono_method (klass, mb);
11145 #else
11146                 g_assert_not_reached ();
11147                 method = NULL;
11148 #endif
11149         } else {
11150                 method = rmethod->method;
11151         }
11152
11153         klass = method->klass;
11154
11155         if (method->is_inflated)
11156                 method = ((MonoMethodInflated *) method)->declaring;
11157
11158         count = mono_method_signature (method)->generic_param_count;
11159         if (count != mono_array_length (types))
11160                 return NULL;
11161
11162         type_argv = g_new0 (MonoType *, count);
11163         for (i = 0; i < count; i++) {
11164                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11165                 type_argv [i] = mono_reflection_type_get_handle (garg);
11166         }
11167         ginst = mono_metadata_get_generic_inst (count, type_argv);
11168         g_free (type_argv);
11169
11170         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11171         tmp_context.method_inst = ginst;
11172
11173         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11174         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11175         imethod = (MonoMethodInflated *) inflated;
11176
11177         /*FIXME but I think this is no longer necessary*/
11178         if (image_is_dynamic (method->klass->image)) {
11179                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11180                 /*
11181                  * This table maps metadata structures representing inflated methods/fields
11182                  * to the reflection objects representing their generic definitions.
11183                  */
11184                 mono_image_lock ((MonoImage*)image);
11185                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11186                 mono_image_unlock ((MonoImage*)image);
11187         }
11188
11189         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11190                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11191         
11192         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11193 }
11194
11195 #ifndef DISABLE_REFLECTION_EMIT
11196
11197 static MonoMethod *
11198 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11199 {
11200         MonoMethodInflated *imethod;
11201         MonoGenericContext *context;
11202         int i;
11203
11204         /*
11205          * With generic code sharing the klass might not be inflated.
11206          * This can happen because classes inflated with their own
11207          * type arguments are "normalized" to the uninflated class.
11208          */
11209         if (!klass->generic_class)
11210                 return method;
11211
11212         context = mono_class_get_context (klass);
11213
11214         if (klass->method.count && klass->methods) {
11215                 /* Find the already created inflated method */
11216                 for (i = 0; i < klass->method.count; ++i) {
11217                         g_assert (klass->methods [i]->is_inflated);
11218                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11219                                 break;
11220                 }
11221                 g_assert (i < klass->method.count);
11222                 imethod = (MonoMethodInflated*)klass->methods [i];
11223         } else {
11224                 MonoError error;
11225                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11226                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11227         }
11228
11229         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11230                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11231
11232                 mono_image_lock ((MonoImage*)image);
11233                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11234                 mono_image_unlock ((MonoImage*)image);
11235         }
11236         return (MonoMethod *) imethod;
11237 }
11238
11239 static MonoMethod *
11240 inflate_method (MonoReflectionType *type, MonoObject *obj)
11241 {
11242         MonoMethod *method;
11243         MonoClass *gklass;
11244
11245         MonoClass *type_class = mono_object_class (type);
11246
11247         if (is_sre_generic_instance (type_class)) {
11248                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11249                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11250         } else if (is_sre_type_builder (type_class)) {
11251                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11252         } else if (type->type) {
11253                 gklass = mono_class_from_mono_type (type->type);
11254                 gklass = mono_class_get_generic_type_definition (gklass);
11255         } else {
11256                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11257         }
11258
11259         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11260                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11261                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11262                 else
11263                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11264         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11265                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11266         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11267                 method = ((MonoReflectionMethod *) obj)->method;
11268         else {
11269                 method = NULL; /* prevent compiler warning */
11270                 g_error ("can't handle type %s", obj->vtable->klass->name);
11271         }
11272
11273         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11274 }
11275
11276 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11277 void
11278 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11279 {
11280         MonoGenericClass *gclass;
11281         MonoDynamicGenericClass *dgclass;
11282         MonoClass *klass, *gklass;
11283         MonoType *gtype;
11284         int i;
11285
11286         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11287         klass = mono_class_from_mono_type (gtype);
11288         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11289         gclass = gtype->data.generic_class;
11290
11291         if (!gclass->is_dynamic)
11292                 return;
11293
11294         dgclass = (MonoDynamicGenericClass *) gclass;
11295
11296         if (dgclass->initialized)
11297                 return;
11298
11299         gklass = gclass->container_class;
11300         mono_class_init (gklass);
11301
11302         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11303
11304         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11305         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11306         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11307
11308         for (i = 0; i < dgclass->count_fields; i++) {
11309                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11310                 MonoClassField *field, *inflated_field = NULL;
11311
11312                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11313                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11314                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11315                         field = ((MonoReflectionField *) obj)->field;
11316                 else {
11317                         field = NULL; /* prevent compiler warning */
11318                         g_assert_not_reached ();
11319                 }
11320
11321                 dgclass->fields [i] = *field;
11322                 dgclass->fields [i].parent = klass;
11323                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11324                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11325                 dgclass->field_generic_types [i] = field->type;
11326                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11327                 dgclass->field_objects [i] = obj;
11328
11329                 if (inflated_field) {
11330                         g_free (inflated_field);
11331                 } else {
11332                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11333                 }
11334         }
11335
11336         dgclass->initialized = TRUE;
11337 }
11338
11339 void
11340 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11341 {
11342         MonoDynamicGenericClass *dgclass;
11343         int i;
11344
11345         g_assert (gclass->is_dynamic);
11346
11347         dgclass = (MonoDynamicGenericClass *)gclass;
11348
11349         for (i = 0; i < dgclass->count_fields; ++i) {
11350                 MonoClassField *field = dgclass->fields + i;
11351                 mono_metadata_free_type (field->type);
11352                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11353         }
11354 }
11355
11356 static void
11357 fix_partial_generic_class (MonoClass *klass)
11358 {
11359         MonoClass *gklass = klass->generic_class->container_class;
11360         MonoDynamicGenericClass *dgclass;
11361         int i;
11362
11363         if (klass->wastypebuilder)
11364                 return;
11365
11366         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11367         if (klass->parent != gklass->parent) {
11368                 MonoError error;
11369                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11370                 if (mono_error_ok (&error)) {
11371                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11372                         mono_metadata_free_type (parent_type);
11373                         if (parent != klass->parent) {
11374                                 /*fool mono_class_setup_parent*/
11375                                 klass->supertypes = NULL;
11376                                 mono_class_setup_parent (klass, parent);
11377                         }
11378                 } else {
11379                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11380                         mono_error_cleanup (&error);
11381                         if (gklass->wastypebuilder)
11382                                 klass->wastypebuilder = TRUE;
11383                         return;
11384                 }
11385         }
11386
11387         if (!dgclass->initialized)
11388                 return;
11389
11390         if (klass->method.count != gklass->method.count) {
11391                 klass->method.count = gklass->method.count;
11392                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11393
11394                 for (i = 0; i < klass->method.count; i++) {
11395                         MonoError error;
11396                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11397                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11398                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11399                 }
11400         }
11401
11402         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11403                 klass->interface_count = gklass->interface_count;
11404                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11405                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11406
11407                 for (i = 0; i < gklass->interface_count; ++i) {
11408                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11409                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11410                         mono_metadata_free_type (iface_type);
11411
11412                         ensure_runtime_vtable (klass->interfaces [i]);
11413                 }
11414                 klass->interfaces_inited = 1;
11415         }
11416
11417         if (klass->field.count != gklass->field.count) {
11418                 klass->field.count = gklass->field.count;
11419                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11420
11421                 for (i = 0; i < klass->field.count; i++) {
11422                         klass->fields [i] = gklass->fields [i];
11423                         klass->fields [i].parent = klass;
11424                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11425                 }
11426         }
11427
11428         /*We can only finish with this klass once it's parent has as well*/
11429         if (gklass->wastypebuilder)
11430                 klass->wastypebuilder = TRUE;
11431         return;
11432 }
11433
11434 static void
11435 ensure_generic_class_runtime_vtable (MonoClass *klass)
11436 {
11437         MonoClass *gklass = klass->generic_class->container_class;
11438
11439         ensure_runtime_vtable (gklass); 
11440
11441         fix_partial_generic_class (klass);
11442 }
11443
11444 static void
11445 ensure_runtime_vtable (MonoClass *klass)
11446 {
11447         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11448         int i, num, j;
11449
11450         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11451                 return;
11452         if (klass->parent)
11453                 ensure_runtime_vtable (klass->parent);
11454
11455         if (tb) {
11456                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11457                 num += tb->num_methods;
11458                 klass->method.count = num;
11459                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11460                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11461                 for (i = 0; i < num; ++i)
11462                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11463                 num = tb->num_methods;
11464                 j = i;
11465                 for (i = 0; i < num; ++i)
11466                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11467         
11468                 if (tb->interfaces) {
11469                         klass->interface_count = mono_array_length (tb->interfaces);
11470                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11471                         for (i = 0; i < klass->interface_count; ++i) {
11472                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11473                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11474                                 ensure_runtime_vtable (klass->interfaces [i]);
11475                         }
11476                         klass->interfaces_inited = 1;
11477                 }
11478         } else if (klass->generic_class){
11479                 ensure_generic_class_runtime_vtable (klass);
11480         }
11481
11482         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11483                 int slot_num = 0;
11484                 for (i = 0; i < klass->method.count; ++i) {
11485                         MonoMethod *im = klass->methods [i];
11486                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11487                                 im->slot = slot_num++;
11488                 }
11489                 
11490                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11491                 mono_class_setup_interface_offsets (klass);
11492                 mono_class_setup_interface_id (klass);
11493         }
11494
11495         /*
11496          * The generic vtable is needed even if image->run is not set since some
11497          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11498          * method->slot being defined.
11499          */
11500
11501         /* 
11502          * tb->methods could not be freed since it is used for determining 
11503          * overrides during dynamic vtable construction.
11504          */
11505 }
11506
11507 static MonoMethod*
11508 mono_reflection_method_get_handle (MonoObject *method)
11509 {
11510         MonoClass *klass = mono_object_class (method);
11511         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11512                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11513                 return sr_method->method;
11514         }
11515         if (is_sre_method_builder (klass)) {
11516                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11517                 return mb->mhandle;
11518         }
11519         if (is_sre_method_on_tb_inst (klass)) {
11520                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11521                 MonoMethod *result;
11522                 /*FIXME move this to a proper method and unify with resolve_object*/
11523                 if (m->method_args) {
11524                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11525                 } else {
11526                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11527                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11528                         MonoMethod *mono_method;
11529
11530                         if (is_sre_method_builder (mono_object_class (m->mb)))
11531                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11532                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11533                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11534                         else
11535                                 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)));
11536
11537                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11538                 }
11539                 return result;
11540         }
11541
11542         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11543         return NULL;
11544 }
11545
11546 void
11547 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11548 {
11549         MonoReflectionTypeBuilder *tb;
11550         int i, j, onum;
11551         MonoReflectionMethod *m;
11552
11553         *overrides = NULL;
11554         *num_overrides = 0;
11555
11556         g_assert (image_is_dynamic (klass->image));
11557
11558         if (!mono_class_get_ref_info (klass))
11559                 return;
11560
11561         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11562
11563         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11564
11565         onum = 0;
11566         if (tb->methods) {
11567                 for (i = 0; i < tb->num_methods; ++i) {
11568                         MonoReflectionMethodBuilder *mb = 
11569                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11570                         if (mb->override_methods)
11571                                 onum += mono_array_length (mb->override_methods);
11572                 }
11573         }
11574
11575         if (onum) {
11576                 *overrides = g_new0 (MonoMethod*, onum * 2);
11577
11578                 onum = 0;
11579                 for (i = 0; i < tb->num_methods; ++i) {
11580                         MonoReflectionMethodBuilder *mb = 
11581                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11582                         if (mb->override_methods) {
11583                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11584                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11585
11586                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11587                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11588
11589                                         g_assert (mb->mhandle);
11590
11591                                         onum ++;
11592                                 }
11593                         }
11594                 }
11595         }
11596
11597         *num_overrides = onum;
11598 }
11599
11600 static void
11601 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11602 {
11603         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11604         MonoReflectionFieldBuilder *fb;
11605         MonoClassField *field;
11606         MonoImage *image = klass->image;
11607         const char *p, *p2;
11608         int i;
11609         guint32 len, idx, real_size = 0;
11610
11611         klass->field.count = tb->num_fields;
11612         klass->field.first = 0;
11613
11614         mono_error_init (error);
11615
11616         if (tb->class_size) {
11617                 if ((tb->packing_size & 0xffffff00) != 0) {
11618                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11619                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11620                         return;
11621                 }
11622                 klass->packing_size = tb->packing_size;
11623                 real_size = klass->instance_size + tb->class_size;
11624         }
11625
11626         if (!klass->field.count) {
11627                 klass->instance_size = MAX (klass->instance_size, real_size);
11628                 return;
11629         }
11630         
11631         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11632         mono_class_alloc_ext (klass);
11633         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11634         /*
11635         This is, guess what, a hack.
11636         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11637         On the static path no field class is resolved, only types are built. This is the right thing to do
11638         but we suck.
11639         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11640         */
11641         klass->size_inited = 1;
11642
11643         for (i = 0; i < klass->field.count; ++i) {
11644                 MonoArray *rva_data;
11645                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11646                 field = &klass->fields [i];
11647                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11648                 if (!mono_error_ok (error))
11649                         return;
11650                 if (fb->attrs) {
11651                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11652                         field->type->attrs = fb->attrs;
11653                 } else {
11654                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11655                 }
11656
11657                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11658                         char *base = mono_array_addr (rva_data, char, 0);
11659                         size_t size = mono_array_length (rva_data);
11660                         char *data = (char *)mono_image_alloc (klass->image, size);
11661                         memcpy (data, base, size);
11662                         klass->ext->field_def_values [i].data = data;
11663                 }
11664                 if (fb->offset != -1)
11665                         field->offset = fb->offset;
11666                 field->parent = klass;
11667                 fb->handle = field;
11668                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11669
11670                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11671                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11672                 }
11673                 if (fb->def_value) {
11674                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11675                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11676                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11677                         /* Copy the data from the blob since it might get realloc-ed */
11678                         p = assembly->blob.data + idx;
11679                         len = mono_metadata_decode_blob_size (p, &p2);
11680                         len += p2 - p;
11681                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11682                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11683                 }
11684         }
11685
11686         klass->instance_size = MAX (klass->instance_size, real_size);
11687         mono_class_layout_fields (klass);
11688 }
11689
11690 static void
11691 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11692 {
11693         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11694         MonoReflectionPropertyBuilder *pb;
11695         MonoImage *image = klass->image;
11696         MonoProperty *properties;
11697         int i;
11698
11699         mono_error_init (error);
11700
11701         if (!klass->ext)
11702                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11703
11704         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11705         klass->ext->property.first = 0;
11706
11707         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11708         klass->ext->properties = properties;
11709         for (i = 0; i < klass->ext->property.count; ++i) {
11710                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11711                 properties [i].parent = klass;
11712                 properties [i].attrs = pb->attrs;
11713                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11714                 if (!mono_error_ok (error))
11715                         return;
11716                 if (pb->get_method)
11717                         properties [i].get = pb->get_method->mhandle;
11718                 if (pb->set_method)
11719                         properties [i].set = pb->set_method->mhandle;
11720
11721                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11722                 if (pb->def_value) {
11723                         guint32 len, idx;
11724                         const char *p, *p2;
11725                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11726                         if (!klass->ext->prop_def_values)
11727                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11728                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11729                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11730                         /* Copy the data from the blob since it might get realloc-ed */
11731                         p = assembly->blob.data + idx;
11732                         len = mono_metadata_decode_blob_size (p, &p2);
11733                         len += p2 - p;
11734                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11735                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11736                 }
11737         }
11738 }
11739
11740 MonoReflectionEvent *
11741 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11742 {
11743         MonoEvent *event = g_new0 (MonoEvent, 1);
11744         MonoClass *klass;
11745
11746         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11747
11748         event->parent = klass;
11749         event->attrs = eb->attrs;
11750         event->name = mono_string_to_utf8 (eb->name);
11751         if (eb->add_method)
11752                 event->add = eb->add_method->mhandle;
11753         if (eb->remove_method)
11754                 event->remove = eb->remove_method->mhandle;
11755         if (eb->raise_method)
11756                 event->raise = eb->raise_method->mhandle;
11757
11758 #ifndef MONO_SMALL_CONFIG
11759         if (eb->other_methods) {
11760                 int j;
11761                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11762                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11763                         MonoReflectionMethodBuilder *mb = 
11764                                 mono_array_get (eb->other_methods,
11765                                                 MonoReflectionMethodBuilder*, j);
11766                         event->other [j] = mb->mhandle;
11767                 }
11768         }
11769 #endif
11770
11771         return mono_event_get_object (mono_object_domain (tb), klass, event);
11772 }
11773
11774 static void
11775 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11776 {
11777         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11778         MonoReflectionEventBuilder *eb;
11779         MonoImage *image = klass->image;
11780         MonoEvent *events;
11781         int i;
11782
11783         mono_error_init (error);
11784
11785         if (!klass->ext)
11786                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11787
11788         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11789         klass->ext->event.first = 0;
11790
11791         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11792         klass->ext->events = events;
11793         for (i = 0; i < klass->ext->event.count; ++i) {
11794                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11795                 events [i].parent = klass;
11796                 events [i].attrs = eb->attrs;
11797                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11798                 if (!mono_error_ok (error))
11799                         return;
11800                 if (eb->add_method)
11801                         events [i].add = eb->add_method->mhandle;
11802                 if (eb->remove_method)
11803                         events [i].remove = eb->remove_method->mhandle;
11804                 if (eb->raise_method)
11805                         events [i].raise = eb->raise_method->mhandle;
11806
11807 #ifndef MONO_SMALL_CONFIG
11808                 if (eb->other_methods) {
11809                         int j;
11810                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11811                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11812                                 MonoReflectionMethodBuilder *mb = 
11813                                         mono_array_get (eb->other_methods,
11814                                                                         MonoReflectionMethodBuilder*, j);
11815                                 events [i].other [j] = mb->mhandle;
11816                         }
11817                 }
11818 #endif
11819                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11820         }
11821 }
11822
11823 static gboolean
11824 remove_instantiations_of_and_ensure_contents (gpointer key,
11825                                                   gpointer value,
11826                                                   gpointer user_data)
11827 {
11828         MonoType *type = (MonoType*)key;
11829         MonoClass *klass = (MonoClass*)user_data;
11830
11831         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11832                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11833                 return TRUE;
11834         } else
11835                 return FALSE;
11836 }
11837
11838 static void
11839 check_array_for_usertypes (MonoArray *arr, MonoError *error)
11840 {
11841         mono_error_init (error);
11842         int i;
11843
11844         if (!arr)
11845                 return;
11846
11847         for (i = 0; i < mono_array_length (arr); ++i) {
11848                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
11849                 if (!mono_error_ok (error))
11850                         break;
11851         }
11852 }
11853
11854 MonoReflectionType*
11855 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11856 {
11857         MonoError error;
11858         MonoClass *klass;
11859         MonoDomain* domain;
11860         MonoReflectionType* res;
11861         int i, j;
11862
11863         domain = mono_object_domain (tb);
11864         klass = mono_class_from_mono_type (tb->type.type);
11865
11866         /*
11867          * Check for user defined Type subclasses.
11868          */
11869         RESOLVE_TYPE (tb->parent, &error);
11870         mono_error_raise_exception (&error); /* FIXME don't raise here */
11871         check_array_for_usertypes (tb->interfaces, &error);
11872         mono_error_raise_exception (&error); /*FIXME don't raise here */
11873         if (tb->fields) {
11874                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11875                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11876                         if (fb) {
11877                                 RESOLVE_TYPE (fb->type, &error);
11878                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11879                                 check_array_for_usertypes (fb->modreq, &error);
11880                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11881                                 check_array_for_usertypes (fb->modopt, &error);
11882                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11883                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
11884                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
11885                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11886                                 }
11887                         }
11888                 }
11889         }
11890         if (tb->methods) {
11891                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11892                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11893                         if (mb) {
11894                                 RESOLVE_TYPE (mb->rtype, &error);
11895                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11896                                 check_array_for_usertypes (mb->return_modreq, &error);
11897                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11898                                 check_array_for_usertypes (mb->return_modopt, &error);
11899                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11900                                 check_array_for_usertypes (mb->parameters, &error);
11901                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11902                                 if (mb->param_modreq)
11903                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11904                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11905                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11906                                         }
11907                                 if (mb->param_modopt)
11908                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11909                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11910                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11911                                         }
11912                         }
11913                 }
11914         }
11915         if (tb->ctors) {
11916                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11917                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11918                         if (mb) {
11919                                 check_array_for_usertypes (mb->parameters, &error);
11920                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11921                                 if (mb->param_modreq)
11922                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
11923                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
11924                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11925                                         }
11926                                 if (mb->param_modopt)
11927                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
11928                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
11929                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
11930                                         }
11931                         }
11932                 }
11933         }
11934
11935         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11936
11937         /* 
11938          * we need to lock the domain because the lock will be taken inside
11939          * So, we need to keep the locking order correct.
11940          */
11941         mono_loader_lock ();
11942         mono_domain_lock (domain);
11943         if (klass->wastypebuilder) {
11944                 mono_domain_unlock (domain);
11945                 mono_loader_unlock ();
11946
11947                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11948                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11949
11950                 return res;
11951         }
11952         /*
11953          * Fields to set in klass:
11954          * the various flags: delegate/unicode/contextbound etc.
11955          */
11956         klass->flags = tb->attrs;
11957         klass->has_cctor = 1;
11958         klass->has_finalize = 1;
11959         klass->has_finalize_inited = 1;
11960
11961         mono_class_setup_parent (klass, klass->parent);
11962         /* fool mono_class_setup_supertypes */
11963         klass->supertypes = NULL;
11964         mono_class_setup_supertypes (klass);
11965         mono_class_setup_mono_type (klass);
11966
11967 #if 0
11968         if (!((MonoDynamicImage*)klass->image)->run) {
11969                 if (klass->generic_container) {
11970                         /* FIXME: The code below can't handle generic classes */
11971                         klass->wastypebuilder = TRUE;
11972                         mono_loader_unlock ();
11973                         mono_domain_unlock (domain);
11974
11975                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
11976                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11977
11978                         return res;
11979                 }
11980         }
11981 #endif
11982
11983         /* enums are done right away */
11984         if (!klass->enumtype)
11985                 ensure_runtime_vtable (klass);
11986
11987         if (tb->subtypes) {
11988                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11989                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11990                         mono_class_alloc_ext (klass);
11991                         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)));
11992                 }
11993         }
11994
11995         klass->nested_classes_inited = TRUE;
11996
11997         /* fields and object layout */
11998         if (klass->parent) {
11999                 if (!klass->parent->size_inited)
12000                         mono_class_init (klass->parent);
12001                 klass->instance_size = klass->parent->instance_size;
12002                 klass->sizes.class_size = 0;
12003                 klass->min_align = klass->parent->min_align;
12004                 /* if the type has no fields we won't call the field_setup
12005                  * routine which sets up klass->has_references.
12006                  */
12007                 klass->has_references |= klass->parent->has_references;
12008         } else {
12009                 klass->instance_size = sizeof (MonoObject);
12010                 klass->min_align = 1;
12011         }
12012
12013         /* FIXME: handle packing_size and instance_size */
12014         typebuilder_setup_fields (klass, &error);
12015         if (!mono_error_ok (&error))
12016                 goto failure;
12017         typebuilder_setup_properties (klass, &error);
12018         if (!mono_error_ok (&error))
12019                 goto failure;
12020
12021         typebuilder_setup_events (klass, &error);
12022         if (!mono_error_ok (&error))
12023                 goto failure;
12024
12025         klass->wastypebuilder = TRUE;
12026
12027         /* 
12028          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12029          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12030          * we want to return normal System.MonoType objects, so clear these out from the cache.
12031          *
12032          * Together with this we must ensure the contents of all instances to match the created type.
12033          */
12034         if (domain->type_hash && klass->generic_container)
12035                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12036
12037         mono_domain_unlock (domain);
12038         mono_loader_unlock ();
12039
12040         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12041                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12042                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12043         }
12044
12045         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12046         mono_error_raise_exception (&error); /* FIXME don't raise here */
12047
12048         g_assert (res != (MonoReflectionType*)tb);
12049
12050         return res;
12051
12052 failure:
12053         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12054         klass->wastypebuilder = TRUE;
12055         mono_domain_unlock (domain);
12056         mono_loader_unlock ();
12057         mono_error_raise_exception (&error);
12058         return NULL;
12059 }
12060
12061 void
12062 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12063 {
12064         MonoGenericParamFull *param;
12065         MonoImage *image;
12066         MonoClass *pklass;
12067         MonoError error;
12068
12069         image = &gparam->tbuilder->module->dynamic_image->image;
12070
12071         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12072
12073         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12074         g_assert (mono_error_ok (&error));
12075         param->param.num = gparam->index;
12076
12077         if (gparam->mbuilder) {
12078                 if (!gparam->mbuilder->generic_container) {
12079                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12080                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12081                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12082                         gparam->mbuilder->generic_container->is_method = TRUE;
12083                         /* 
12084                          * Cannot set owner.method, since the MonoMethod is not created yet.
12085                          * Set the image field instead, so type_in_image () works.
12086                          */
12087                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12088                         gparam->mbuilder->generic_container->owner.image = klass->image;
12089                 }
12090                 param->param.owner = gparam->mbuilder->generic_container;
12091         } else if (gparam->tbuilder) {
12092                 if (!gparam->tbuilder->generic_container) {
12093                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12094                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12095                         gparam->tbuilder->generic_container->owner.klass = klass;
12096                 }
12097                 param->param.owner = gparam->tbuilder->generic_container;
12098         }
12099
12100         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12101
12102         gparam->type.type = &pklass->byval_arg;
12103
12104         mono_class_set_ref_info (pklass, gparam);
12105         mono_image_append_class_to_reflection_info_set (pklass);
12106 }
12107
12108 MonoArray *
12109 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12110 {
12111         MonoError error;
12112         MonoReflectionModuleBuilder *module = sig->module;
12113         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12114         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12115         guint32 buflen, i;
12116         MonoArray *result;
12117         SigBuffer buf;
12118
12119         check_array_for_usertypes (sig->arguments, &error);
12120         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12121
12122         sigbuffer_init (&buf, 32);
12123
12124         sigbuffer_add_value (&buf, 0x07);
12125         sigbuffer_add_value (&buf, na);
12126         if (assembly != NULL){
12127                 for (i = 0; i < na; ++i) {
12128                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12129                         encode_reflection_type (assembly, type, &buf);
12130                 }
12131         }
12132
12133         buflen = buf.p - buf.buf;
12134         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12135         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12136         sigbuffer_free (&buf);
12137
12138         return result;
12139 }
12140
12141 MonoArray *
12142 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12143 {
12144         MonoError error;
12145         MonoDynamicImage *assembly = sig->module->dynamic_image;
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, 0x06);
12157         for (i = 0; i < na; ++i) {
12158                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12159                 encode_reflection_type (assembly, type, &buf);
12160         }
12161
12162         buflen = buf.p - buf.buf;
12163         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12164         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12165         sigbuffer_free (&buf);
12166
12167         return result;
12168 }
12169
12170 typedef struct {
12171         MonoMethod *handle;
12172         MonoDomain *domain;
12173 } DynamicMethodReleaseData;
12174
12175 /*
12176  * The runtime automatically clean up those after finalization.
12177 */      
12178 static MonoReferenceQueue *dynamic_method_queue;
12179
12180 static void
12181 free_dynamic_method (void *dynamic_method)
12182 {
12183         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12184         MonoDomain *domain = data->domain;
12185         MonoMethod *method = data->handle;
12186         guint32 dis_link;
12187
12188         mono_domain_lock (domain);
12189         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12190         g_hash_table_remove (domain->method_to_dyn_method, method);
12191         mono_domain_unlock (domain);
12192         g_assert (dis_link);
12193         mono_gchandle_free (dis_link);
12194
12195         mono_runtime_free_method (domain, method);
12196         g_free (data);
12197 }
12198
12199 void 
12200 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12201 {
12202         MonoReferenceQueue *queue;
12203         MonoMethod *handle;
12204         DynamicMethodReleaseData *release_data;
12205         ReflectionMethodBuilder rmb;
12206         MonoMethodSignature *sig;
12207         MonoClass *klass;
12208         MonoDomain *domain;
12209         GSList *l;
12210         int i;
12211
12212         if (mono_runtime_is_shutting_down ())
12213                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12214
12215         if (!(queue = dynamic_method_queue)) {
12216                 mono_loader_lock ();
12217                 if (!(queue = dynamic_method_queue))
12218                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12219                 mono_loader_unlock ();
12220         }
12221
12222         sig = dynamic_method_to_signature (mb);
12223
12224         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12225
12226         /*
12227          * Resolve references.
12228          */
12229         /* 
12230          * Every second entry in the refs array is reserved for storing handle_class,
12231          * which is needed by the ldtoken implementation in the JIT.
12232          */
12233         rmb.nrefs = mb->nrefs;
12234         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12235         for (i = 0; i < mb->nrefs; i += 2) {
12236                 MonoClass *handle_class;
12237                 gpointer ref;
12238                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12239
12240                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12241                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12242                         /*
12243                          * The referenced DynamicMethod should already be created by the managed
12244                          * code, except in the case of circular references. In that case, we store
12245                          * method in the refs array, and fix it up later when the referenced 
12246                          * DynamicMethod is created.
12247                          */
12248                         if (method->mhandle) {
12249                                 ref = method->mhandle;
12250                         } else {
12251                                 /* FIXME: GC object stored in unmanaged memory */
12252                                 ref = method;
12253
12254                                 /* FIXME: GC object stored in unmanaged memory */
12255                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12256                         }
12257                         handle_class = mono_defaults.methodhandle_class;
12258                 } else {
12259                         MonoException *ex = NULL;
12260                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12261                         if (!ref)
12262                                 ex = mono_get_exception_type_load (NULL, NULL);
12263                         else if (mono_security_core_clr_enabled ())
12264                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12265
12266                         if (ex) {
12267                                 g_free (rmb.refs);
12268                                 mono_raise_exception (ex);
12269                                 return;
12270                         }
12271                 }
12272
12273                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12274                 rmb.refs [i + 1] = handle_class;
12275         }               
12276
12277         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12278
12279         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12280         release_data = g_new (DynamicMethodReleaseData, 1);
12281         release_data->handle = handle;
12282         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12283         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12284                 g_free (release_data);
12285
12286         /* Fix up refs entries pointing at us */
12287         for (l = mb->referenced_by; l; l = l->next) {
12288                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12289                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12290                 gpointer *data;
12291                 
12292                 g_assert (method->mhandle);
12293
12294                 data = (gpointer*)wrapper->method_data;
12295                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12296                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12297                                 data [i + 1] = mb->mhandle;
12298                 }
12299         }
12300         g_slist_free (mb->referenced_by);
12301
12302         g_free (rmb.refs);
12303
12304         /* ilgen is no longer needed */
12305         mb->ilgen = NULL;
12306
12307         domain = mono_domain_get ();
12308         mono_domain_lock (domain);
12309         if (!domain->method_to_dyn_method)
12310                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12311         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12312         mono_domain_unlock (domain);
12313 }
12314
12315 #endif /* DISABLE_REFLECTION_EMIT */
12316
12317 /**
12318  * 
12319  * mono_reflection_is_valid_dynamic_token:
12320  * 
12321  * Returns TRUE if token is valid.
12322  * 
12323  */
12324 gboolean
12325 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12326 {
12327         return lookup_dyn_token (image, token) != NULL;
12328 }
12329
12330 MonoMethodSignature *
12331 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12332 {
12333         MonoMethodSignature *sig;
12334         g_assert (image_is_dynamic (image));
12335
12336         mono_error_init (error);
12337
12338         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12339         if (sig)
12340                 return sig;
12341
12342         return mono_method_signature_checked (method, error);
12343 }
12344
12345 #ifndef DISABLE_REFLECTION_EMIT
12346
12347 /**
12348  * mono_reflection_lookup_dynamic_token:
12349  *
12350  * Finish the Builder object pointed to by TOKEN and return the corresponding
12351  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12352  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12353  * mapping table.
12354  *
12355  * LOCKING: Take the loader lock
12356  */
12357 gpointer
12358 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12359 {
12360         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12361         MonoObject *obj;
12362         MonoClass *klass;
12363
12364         obj = lookup_dyn_token (assembly, token);
12365         if (!obj) {
12366                 if (valid_token)
12367                         g_error ("Could not find required dynamic token 0x%08x", token);
12368                 else
12369                         return NULL;
12370         }
12371
12372         if (!handle_class)
12373                 handle_class = &klass;
12374         return resolve_object (image, obj, handle_class, context);
12375 }
12376
12377 /*
12378  * ensure_complete_type:
12379  *
12380  *   Ensure that KLASS is completed if it is a dynamic type, or references
12381  * dynamic types.
12382  */
12383 static void
12384 ensure_complete_type (MonoClass *klass)
12385 {
12386         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12387                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12388
12389                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12390
12391                 // Asserting here could break a lot of code
12392                 //g_assert (klass->wastypebuilder);
12393         }
12394
12395         if (klass->generic_class) {
12396                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12397                 int i;
12398
12399                 for (i = 0; i < inst->type_argc; ++i) {
12400                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12401                 }
12402         }
12403 }
12404
12405 static gpointer
12406 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12407 {
12408         gpointer result = NULL;
12409
12410         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12411                 result = mono_string_intern ((MonoString*)obj);
12412                 *handle_class = mono_defaults.string_class;
12413                 g_assert (result);
12414         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12415                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12416                 MonoClass *mc = mono_class_from_mono_type (type);
12417                 if (!mono_class_init (mc))
12418                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12419
12420                 if (context) {
12421                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12422                         result = mono_class_from_mono_type (inflated);
12423                         mono_metadata_free_type (inflated);
12424                 } else {
12425                         result = mono_class_from_mono_type (type);
12426                 }
12427                 *handle_class = mono_defaults.typehandle_class;
12428                 g_assert (result);
12429         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12430                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12431                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12432                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12433                 result = ((MonoReflectionMethod*)obj)->method;
12434                 if (context) {
12435                         MonoError error;
12436                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12437                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12438                 }
12439                 *handle_class = mono_defaults.methodhandle_class;
12440                 g_assert (result);
12441         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12442                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12443                 result = mb->mhandle;
12444                 if (!result) {
12445                         /* Type is not yet created */
12446                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12447
12448                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12449
12450                         /*
12451                          * Hopefully this has been filled in by calling CreateType() on the
12452                          * TypeBuilder.
12453                          */
12454                         /*
12455                          * TODO: This won't work if the application finishes another 
12456                          * TypeBuilder instance instead of this one.
12457                          */
12458                         result = mb->mhandle;
12459                 }
12460                 if (context) {
12461                         MonoError error;
12462                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12463                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12464                 }
12465                 *handle_class = mono_defaults.methodhandle_class;
12466         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12467                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12468
12469                 result = cb->mhandle;
12470                 if (!result) {
12471                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12472
12473                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12474                         result = cb->mhandle;
12475                 }
12476                 if (context) {
12477                         MonoError error;
12478                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12479                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12480                 }
12481                 *handle_class = mono_defaults.methodhandle_class;
12482         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12483                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12484
12485                 ensure_complete_type (field->parent);
12486                 if (context) {
12487                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12488                         MonoClass *klass = mono_class_from_mono_type (inflated);
12489                         MonoClassField *inflated_field;
12490                         gpointer iter = NULL;
12491                         mono_metadata_free_type (inflated);
12492                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12493                                 if (!strcmp (field->name, inflated_field->name))
12494                                         break;
12495                         }
12496                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12497                         result = inflated_field;
12498                 } else {
12499                         result = field;
12500                 }
12501                 *handle_class = mono_defaults.fieldhandle_class;
12502                 g_assert (result);
12503         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12504                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12505                 result = fb->handle;
12506
12507                 if (!result) {
12508                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12509
12510                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12511                         result = fb->handle;
12512                 }
12513
12514                 if (fb->handle && fb->handle->parent->generic_container) {
12515                         MonoClass *klass = fb->handle->parent;
12516                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12517                         MonoClass *inflated = mono_class_from_mono_type (type);
12518
12519                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12520                         g_assert (result);
12521                         mono_metadata_free_type (type);
12522                 }
12523                 *handle_class = mono_defaults.fieldhandle_class;
12524         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12525                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12526                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12527                 MonoClass *klass;
12528
12529                 klass = type->data.klass;
12530                 if (klass->wastypebuilder) {
12531                         /* Already created */
12532                         result = klass;
12533                 }
12534                 else {
12535                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12536                         result = type->data.klass;
12537                         g_assert (result);
12538                 }
12539                 *handle_class = mono_defaults.typehandle_class;
12540         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12541                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12542                 MonoMethodSignature *sig;
12543                 int nargs, i;
12544
12545                 if (helper->arguments)
12546                         nargs = mono_array_length (helper->arguments);
12547                 else
12548                         nargs = 0;
12549
12550                 sig = mono_metadata_signature_alloc (image, nargs);
12551                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12552                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12553
12554                 if (helper->unmanaged_call_conv) { /* unmanaged */
12555                         sig->call_convention = helper->unmanaged_call_conv - 1;
12556                         sig->pinvoke = TRUE;
12557                 } else if (helper->call_conv & 0x02) {
12558                         sig->call_convention = MONO_CALL_VARARG;
12559                 } else {
12560                         sig->call_convention = MONO_CALL_DEFAULT;
12561                 }
12562
12563                 sig->param_count = nargs;
12564                 /* TODO: Copy type ? */
12565                 sig->ret = helper->return_type->type;
12566                 for (i = 0; i < nargs; ++i)
12567                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12568
12569                 result = sig;
12570                 *handle_class = NULL;
12571         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12572                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12573                 /* Already created by the managed code */
12574                 g_assert (method->mhandle);
12575                 result = method->mhandle;
12576                 *handle_class = mono_defaults.methodhandle_class;
12577         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12578                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12579                 type = mono_class_inflate_generic_type (type, context);
12580                 result = mono_class_from_mono_type (type);
12581                 *handle_class = mono_defaults.typehandle_class;
12582                 g_assert (result);
12583                 mono_metadata_free_type (type);
12584         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12585                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12586                 type = mono_class_inflate_generic_type (type, context);
12587                 result = mono_class_from_mono_type (type);
12588                 *handle_class = mono_defaults.typehandle_class;
12589                 g_assert (result);
12590                 mono_metadata_free_type (type);
12591         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12592                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12593                 MonoClass *inflated;
12594                 MonoType *type;
12595                 MonoClassField *field;
12596
12597                 if (is_sre_field_builder (mono_object_class (f->fb)))
12598                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12599                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12600                         field = ((MonoReflectionField*)f->fb)->field;
12601                 else
12602                         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)));
12603
12604                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12605                 inflated = mono_class_from_mono_type (type);
12606
12607                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12608                 ensure_complete_type (field->parent);
12609                 g_assert (result);
12610                 mono_metadata_free_type (type);
12611                 *handle_class = mono_defaults.fieldhandle_class;
12612         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12613                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12614                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12615                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12616                 MonoMethod *method;
12617
12618                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12619                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12620                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12621                         method = ((MonoReflectionMethod *)c->cb)->method;
12622                 else
12623                         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)));
12624
12625                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12626                 *handle_class = mono_defaults.methodhandle_class;
12627                 mono_metadata_free_type (type);
12628         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12629                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12630                 if (m->method_args) {
12631                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12632                         if (context) {
12633                                 MonoError error;
12634                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12635                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12636                         }
12637                 } else {
12638                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12639                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12640                         MonoMethod *method;
12641
12642                         if (is_sre_method_builder (mono_object_class (m->mb)))
12643                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12644                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12645                                 method = ((MonoReflectionMethod *)m->mb)->method;
12646                         else
12647                                 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)));
12648
12649                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12650                         mono_metadata_free_type (type);
12651                 }
12652                 *handle_class = mono_defaults.methodhandle_class;
12653         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12654                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12655                 MonoType *mtype;
12656                 MonoClass *klass;
12657                 MonoMethod *method;
12658                 gpointer iter;
12659                 char *name;
12660
12661                 mtype = mono_reflection_type_get_handle (m->parent);
12662                 klass = mono_class_from_mono_type (mtype);
12663
12664                 /* Find the method */
12665
12666                 name = mono_string_to_utf8 (m->name);
12667                 iter = NULL;
12668                 while ((method = mono_class_get_methods (klass, &iter))) {
12669                         if (!strcmp (method->name, name))
12670                                 break;
12671                 }
12672                 g_free (name);
12673
12674                 // FIXME:
12675                 g_assert (method);
12676                 // FIXME: Check parameters/return value etc. match
12677
12678                 result = method;
12679                 *handle_class = mono_defaults.methodhandle_class;
12680         } else if (is_sre_array (mono_object_get_class(obj)) ||
12681                                 is_sre_byref (mono_object_get_class(obj)) ||
12682                                 is_sre_pointer (mono_object_get_class(obj))) {
12683                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12684                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12685
12686                 if (context) {
12687                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12688                         result = mono_class_from_mono_type (inflated);
12689                         mono_metadata_free_type (inflated);
12690                 } else {
12691                         result = mono_class_from_mono_type (type);
12692                 }
12693                 *handle_class = mono_defaults.typehandle_class;
12694         } else {
12695                 g_print ("%s\n", obj->vtable->klass->name);
12696                 g_assert_not_reached ();
12697         }
12698         return result;
12699 }
12700
12701 #else /* DISABLE_REFLECTION_EMIT */
12702
12703 MonoArray*
12704 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12705 {
12706         g_assert_not_reached ();
12707         return NULL;
12708 }
12709
12710 void
12711 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12712 {
12713         g_assert_not_reached ();
12714 }
12715
12716 void
12717 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12718 {
12719         g_assert_not_reached ();
12720 }
12721
12722 void
12723 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12724 {
12725         g_assert_not_reached ();
12726 }
12727
12728 void
12729 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12730 {
12731         g_assert_not_reached ();
12732 }
12733
12734 void
12735 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12736 {
12737         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12738 }
12739
12740 void
12741 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12742 {
12743         g_assert_not_reached ();
12744 }
12745
12746 void
12747 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12748 {
12749         g_assert_not_reached ();
12750 }
12751
12752 MonoReflectionModule *
12753 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12754 {
12755         g_assert_not_reached ();
12756         return NULL;
12757 }
12758
12759 guint32
12760 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12761 {
12762         g_assert_not_reached ();
12763         return 0;
12764 }
12765
12766 guint32
12767 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12768 {
12769         g_assert_not_reached ();
12770         return 0;
12771 }
12772
12773 guint32
12774 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12775                                                  gboolean create_open_instance, gboolean register_token)
12776 {
12777         g_assert_not_reached ();
12778         return 0;
12779 }
12780
12781 void
12782 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12783 {
12784 }
12785
12786 void
12787 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12788 {
12789         g_assert_not_reached ();
12790 }
12791
12792 void
12793 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12794 {
12795         *overrides = NULL;
12796         *num_overrides = 0;
12797 }
12798
12799 MonoReflectionEvent *
12800 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12801 {
12802         g_assert_not_reached ();
12803         return NULL;
12804 }
12805
12806 MonoReflectionType*
12807 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12808 {
12809         g_assert_not_reached ();
12810         return NULL;
12811 }
12812
12813 void
12814 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12815 {
12816         g_assert_not_reached ();
12817 }
12818
12819 MonoArray *
12820 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12821 {
12822         g_assert_not_reached ();
12823         return NULL;
12824 }
12825
12826 MonoArray *
12827 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12828 {
12829         g_assert_not_reached ();
12830         return NULL;
12831 }
12832
12833 void 
12834 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12835 {
12836 }
12837
12838 gpointer
12839 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12840 {
12841         return NULL;
12842 }
12843
12844 MonoType*
12845 mono_reflection_type_get_handle (MonoReflectionType* ref)
12846 {
12847         if (!ref)
12848                 return NULL;
12849         return ref->type;
12850 }
12851
12852 void
12853 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12854 {
12855         g_assert_not_reached ();
12856 }
12857
12858 #endif /* DISABLE_REFLECTION_EMIT */
12859
12860 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12861 const static guint32 declsec_flags_map[] = {
12862         0x00000000,                                     /* empty */
12863         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12864         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12865         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12866         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12867         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12868         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12869         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12870         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12871         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12872         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12873         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12874         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12875         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12876         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12877         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12878         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12879         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12880         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12881 };
12882
12883 /*
12884  * Returns flags that includes all available security action associated to the handle.
12885  * @token: metadata token (either for a class or a method)
12886  * @image: image where resides the metadata.
12887  */
12888 static guint32
12889 mono_declsec_get_flags (MonoImage *image, guint32 token)
12890 {
12891         int index = mono_metadata_declsec_from_index (image, token);
12892         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12893         guint32 result = 0;
12894         guint32 action;
12895         int i;
12896
12897         /* HasSecurity can be present for other, not specially encoded, attributes,
12898            e.g. SuppressUnmanagedCodeSecurityAttribute */
12899         if (index < 0)
12900                 return 0;
12901
12902         for (i = index; i < t->rows; i++) {
12903                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12904
12905                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12906                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12907                         break;
12908
12909                 action = cols [MONO_DECL_SECURITY_ACTION];
12910                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12911                         result |= declsec_flags_map [action];
12912                 } else {
12913                         g_assert_not_reached ();
12914                 }
12915         }
12916         return result;
12917 }
12918
12919 /*
12920  * Get the security actions (in the form of flags) associated with the specified method.
12921  *
12922  * @method: The method for which we want the declarative security flags.
12923  * Return the declarative security flags for the method (only).
12924  *
12925  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12926  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12927  */
12928 guint32
12929 mono_declsec_flags_from_method (MonoMethod *method)
12930 {
12931         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12932                 /* FIXME: No cache (for the moment) */
12933                 guint32 idx = mono_method_get_index (method);
12934                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12935                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12936                 return mono_declsec_get_flags (method->klass->image, idx);
12937         }
12938         return 0;
12939 }
12940
12941 /*
12942  * Get the security actions (in the form of flags) associated with the specified class.
12943  *
12944  * @klass: The class for which we want the declarative security flags.
12945  * Return the declarative security flags for the class.
12946  *
12947  * Note: We cache the flags inside the MonoClass structure as this will get 
12948  *       called very often (at least for each method).
12949  */
12950 guint32
12951 mono_declsec_flags_from_class (MonoClass *klass)
12952 {
12953         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12954                 if (!klass->ext || !klass->ext->declsec_flags) {
12955                         guint32 idx;
12956
12957                         idx = mono_metadata_token_index (klass->type_token);
12958                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12959                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12960                         mono_loader_lock ();
12961                         mono_class_alloc_ext (klass);
12962                         mono_loader_unlock ();
12963                         /* we cache the flags on classes */
12964                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12965                 }
12966                 return klass->ext->declsec_flags;
12967         }
12968         return 0;
12969 }
12970
12971 /*
12972  * Get the security actions (in the form of flags) associated with the specified assembly.
12973  *
12974  * @assembly: The assembly for which we want the declarative security flags.
12975  * Return the declarative security flags for the assembly.
12976  */
12977 guint32
12978 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12979 {
12980         guint32 idx = 1; /* there is only one assembly */
12981         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12982         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12983         return mono_declsec_get_flags (assembly->image, idx);
12984 }
12985
12986
12987 /*
12988  * Fill actions for the specific index (which may either be an encoded class token or
12989  * an encoded method token) from the metadata image.
12990  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12991  */
12992 static MonoBoolean
12993 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12994         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12995 {
12996         MonoBoolean result = FALSE;
12997         MonoTableInfo *t;
12998         guint32 cols [MONO_DECL_SECURITY_SIZE];
12999         int index = mono_metadata_declsec_from_index (image, token);
13000         int i;
13001
13002         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13003         for (i = index; i < t->rows; i++) {
13004                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13005
13006                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13007                         return result;
13008
13009                 /* if present only replace (class) permissions with method permissions */
13010                 /* if empty accept either class or method permissions */
13011                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13012                         if (!actions->demand.blob) {
13013                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13014                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13015                                 actions->demand.blob = (char*) (blob + 2);
13016                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13017                                 result = TRUE;
13018                         }
13019                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13020                         if (!actions->noncasdemand.blob) {
13021                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13022                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13023                                 actions->noncasdemand.blob = (char*) (blob + 2);
13024                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13025                                 result = TRUE;
13026                         }
13027                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13028                         if (!actions->demandchoice.blob) {
13029                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13030                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13031                                 actions->demandchoice.blob = (char*) (blob + 2);
13032                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13033                                 result = TRUE;
13034                         }
13035                 }
13036         }
13037
13038         return result;
13039 }
13040
13041 static MonoBoolean
13042 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13043         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13044 {
13045         guint32 idx = mono_metadata_token_index (klass->type_token);
13046         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13047         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13048         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13049 }
13050
13051 static MonoBoolean
13052 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13053         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13054 {
13055         guint32 idx = mono_method_get_index (method);
13056         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13057         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13058         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13059 }
13060
13061 /*
13062  * Collect all actions (that requires to generate code in mini) assigned for
13063  * the specified method.
13064  * Note: Don't use the content of actions if the function return FALSE.
13065  */
13066 MonoBoolean
13067 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13068 {
13069         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13070                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13071         MonoBoolean result = FALSE;
13072         guint32 flags;
13073
13074         /* quick exit if no declarative security is present in the metadata */
13075         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13076                 return FALSE;
13077
13078         /* we want the original as the wrapper is "free" of the security informations */
13079         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13080                 method = mono_marshal_method_from_wrapper (method);
13081                 if (!method)
13082                         return FALSE;
13083         }
13084
13085         /* First we look for method-level attributes */
13086         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13087                 mono_class_init (method->klass);
13088                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13089
13090                 result = mono_declsec_get_method_demands_params (method, demands, 
13091                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13092         }
13093
13094         /* Here we use (or create) the class declarative cache to look for demands */
13095         flags = mono_declsec_flags_from_class (method->klass);
13096         if (flags & mask) {
13097                 if (!result) {
13098                         mono_class_init (method->klass);
13099                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13100                 }
13101                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13102                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13103         }
13104
13105         /* The boolean return value is used as a shortcut in case nothing needs to
13106            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13107         return result;
13108 }
13109
13110
13111 /*
13112  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13113  *
13114  * Note: Don't use the content of actions if the function return FALSE.
13115  */
13116 MonoBoolean
13117 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13118 {
13119         MonoBoolean result = FALSE;
13120         guint32 flags;
13121
13122         /* quick exit if no declarative security is present in the metadata */
13123         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13124                 return FALSE;
13125
13126         /* we want the original as the wrapper is "free" of the security informations */
13127         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13128                 method = mono_marshal_method_from_wrapper (method);
13129                 if (!method)
13130                         return FALSE;
13131         }
13132
13133         /* results are independant - zeroize both */
13134         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13135         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13136
13137         /* First we look for method-level attributes */
13138         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13139                 mono_class_init (method->klass);
13140
13141                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13142                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13143         }
13144
13145         /* Here we use (or create) the class declarative cache to look for demands */
13146         flags = mono_declsec_flags_from_class (method->klass);
13147         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13148                 mono_class_init (method->klass);
13149
13150                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13151                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13152         }
13153
13154         return result;
13155 }
13156
13157 /*
13158  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13159  *
13160  * @klass       The inherited class - this is the class that provides the security check (attributes)
13161  * @demans      
13162  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13163  * 
13164  * Note: Don't use the content of actions if the function return FALSE.
13165  */
13166 MonoBoolean
13167 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13168 {
13169         MonoBoolean result = FALSE;
13170         guint32 flags;
13171
13172         /* quick exit if no declarative security is present in the metadata */
13173         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13174                 return FALSE;
13175
13176         /* Here we use (or create) the class declarative cache to look for demands */
13177         flags = mono_declsec_flags_from_class (klass);
13178         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13179                 mono_class_init (klass);
13180                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13181
13182                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13183                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13184         }
13185
13186         return result;
13187 }
13188
13189 /*
13190  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13191  *
13192  * Note: Don't use the content of actions if the function return FALSE.
13193  */
13194 MonoBoolean
13195 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13196 {
13197         /* quick exit if no declarative security is present in the metadata */
13198         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13199                 return FALSE;
13200
13201         /* we want the original as the wrapper is "free" of the security informations */
13202         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13203                 method = mono_marshal_method_from_wrapper (method);
13204                 if (!method)
13205                         return FALSE;
13206         }
13207
13208         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13209                 mono_class_init (method->klass);
13210                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13211
13212                 return mono_declsec_get_method_demands_params (method, demands, 
13213                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13214         }
13215         return FALSE;
13216 }
13217
13218
13219 static MonoBoolean
13220 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13221 {
13222         guint32 cols [MONO_DECL_SECURITY_SIZE];
13223         MonoTableInfo *t;
13224         int i;
13225
13226         int index = mono_metadata_declsec_from_index (image, token);
13227         if (index == -1)
13228                 return FALSE;
13229
13230         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13231         for (i = index; i < t->rows; i++) {
13232                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13233
13234                 /* shortcut - index are ordered */
13235                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13236                         return FALSE;
13237
13238                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13239                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13240                         entry->blob = (char*) (metadata + 2);
13241                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13242                         return TRUE;
13243                 }
13244         }
13245
13246         return FALSE;
13247 }
13248
13249 MonoBoolean
13250 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13251 {
13252         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13253                 guint32 idx = mono_method_get_index (method);
13254                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13255                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13256                 return get_declsec_action (method->klass->image, idx, action, entry);
13257         }
13258         return FALSE;
13259 }
13260
13261 MonoBoolean
13262 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13263 {
13264         /* use cache */
13265         guint32 flags = mono_declsec_flags_from_class (klass);
13266         if (declsec_flags_map [action] & flags) {
13267                 guint32 idx = mono_metadata_token_index (klass->type_token);
13268                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13269                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13270                 return get_declsec_action (klass->image, idx, action, entry);
13271         }
13272         return FALSE;
13273 }
13274
13275 MonoBoolean
13276 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13277 {
13278         guint32 idx = 1; /* there is only one assembly */
13279         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13280         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13281
13282         return get_declsec_action (assembly->image, idx, action, entry);
13283 }
13284
13285 gboolean
13286 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13287 {
13288         MonoError error;
13289         MonoObject *res, *exc;
13290         void *params [1];
13291         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13292         static MonoMethod *method = NULL;
13293
13294         if (!System_Reflection_Emit_TypeBuilder) {
13295                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13296                 g_assert (System_Reflection_Emit_TypeBuilder);
13297         }
13298         if (method == NULL) {
13299                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13300                 g_assert (method);
13301         }
13302
13303         /* 
13304          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13305          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13306          */
13307         g_assert (mono_class_get_ref_info (klass));
13308         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13309
13310         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13311         mono_error_raise_exception (&error); /* FIXME don't raise here */
13312
13313         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13314         if (exc)
13315                 return FALSE;
13316         else
13317                 return *(MonoBoolean*)mono_object_unbox (res);
13318 }
13319
13320 /**
13321  * mono_reflection_type_get_type:
13322  * @reftype: the System.Type object
13323  *
13324  * Returns the MonoType* associated with the C# System.Type object @reftype.
13325  */
13326 MonoType*
13327 mono_reflection_type_get_type (MonoReflectionType *reftype)
13328 {
13329         g_assert (reftype);
13330
13331         return mono_reflection_type_get_handle (reftype);
13332 }
13333
13334 /**
13335  * mono_reflection_assembly_get_assembly:
13336  * @refassembly: the System.Reflection.Assembly object
13337  *
13338  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13339  */
13340 MonoAssembly*
13341 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13342 {
13343         g_assert (refassembly);
13344
13345         return refassembly->assembly;
13346 }
13347