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