Convert MonoGenericContainer/Param accessor macros to inline functions
[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);
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);
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) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
198 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
199         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
200         __type = mono_reflection_type_resolve_user_types (__type);      \
201         mono_array_set (arr, MonoReflectionType*, index, __type);       \
202 } while (0)
203
204 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205
206 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
207 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
208
209 #if SIZEOF_VOID_P == 4
210 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
211 #else
212 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
213 #endif
214
215 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
216 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
217
218 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
219 static GPtrArray *dynamic_images;
220 static mono_mutex_t dynamic_images_mutex;
221
222 static inline void
223 dynamic_images_lock (void)
224 {
225         mono_mutex_lock (&dynamic_images_mutex);
226 }
227
228 static inline void
229 dynamic_images_unlock (void)
230 {
231         mono_mutex_unlock (&dynamic_images_mutex);
232 }
233
234 /**
235  * mono_find_dynamic_image_owner:
236  *
237  * Find the dynamic image, if any, which a given pointer is located in the memory of.
238  */
239 MonoImage *
240 mono_find_dynamic_image_owner (void *ptr)
241 {
242         MonoImage *owner = NULL;
243         int i;
244
245         dynamic_images_lock ();
246
247         if (dynamic_images)
248         {
249                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
250                         MonoImage *image = g_ptr_array_index (dynamic_images, i);
251                         if (mono_mempool_contains_addr (image->mempool, ptr))
252                                 owner = image;
253                 }
254         }
255
256         dynamic_images_unlock ();
257
258         return owner;
259 }
260
261 void
262 mono_reflection_init (void)
263 {
264 }
265
266 static inline void
267 dynamic_image_lock (MonoDynamicImage *image)
268 {
269         MONO_TRY_BLOCKING;
270         mono_image_lock ((MonoImage*)image);
271         MONO_FINISH_TRY_BLOCKING;
272 }
273
274 static inline void
275 dynamic_image_unlock (MonoDynamicImage *image)
276 {
277         mono_image_unlock ((MonoImage*)image);
278 }
279
280 static void
281 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
282 {
283         MONO_REQ_GC_UNSAFE_MODE;
284
285         dynamic_image_lock (assembly);
286         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
287         dynamic_image_unlock (assembly);
288 }
289
290 static MonoObject*
291 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
292 {
293         MONO_REQ_GC_UNSAFE_MODE;
294
295         MonoObject *obj;
296
297         dynamic_image_lock (assembly);
298         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
299         dynamic_image_unlock (assembly);
300
301         return obj;
302 }
303
304 static void
305 sigbuffer_init (SigBuffer *buf, int size)
306 {
307         MONO_REQ_GC_NEUTRAL_MODE;
308
309         buf->buf = g_malloc (size);
310         buf->p = buf->buf;
311         buf->end = buf->buf + size;
312 }
313
314 static void
315 sigbuffer_make_room (SigBuffer *buf, int size)
316 {
317         MONO_REQ_GC_NEUTRAL_MODE;
318
319         if (buf->end - buf->p < size) {
320                 int new_size = buf->end - buf->buf + size + 32;
321                 char *p = g_realloc (buf->buf, new_size);
322                 size = buf->p - buf->buf;
323                 buf->buf = p;
324                 buf->p = p + size;
325                 buf->end = buf->buf + new_size;
326         }
327 }
328
329 static void
330 sigbuffer_add_value (SigBuffer *buf, guint32 val)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         sigbuffer_make_room (buf, 6);
335         mono_metadata_encode_value (val, buf->p, &buf->p);
336 }
337
338 static void
339 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
340 {
341         MONO_REQ_GC_NEUTRAL_MODE;
342
343         sigbuffer_make_room (buf, 1);
344         buf->p [0] = val;
345         buf->p++;
346 }
347
348 static void
349 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
350 {
351         MONO_REQ_GC_NEUTRAL_MODE;
352
353         sigbuffer_make_room (buf, size);
354         memcpy (buf->p, p, size);
355         buf->p += size;
356 }
357
358 static void
359 sigbuffer_free (SigBuffer *buf)
360 {
361         MONO_REQ_GC_NEUTRAL_MODE;
362
363         g_free (buf->buf);
364 }
365
366 #ifndef DISABLE_REFLECTION_EMIT
367 /**
368  * mp_g_alloc:
369  *
370  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
371  * from the C heap.
372  */
373 static gpointer
374 image_g_malloc (MonoImage *image, guint size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         if (image)
379                 return mono_image_alloc (image, size);
380         else
381                 return g_malloc (size);
382 }
383 #endif /* !DISABLE_REFLECTION_EMIT */
384
385 /**
386  * image_g_alloc0:
387  *
388  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
389  * from the C heap.
390  */
391 static gpointer
392 image_g_malloc0 (MonoImage *image, guint size)
393 {
394         MONO_REQ_GC_NEUTRAL_MODE;
395
396         if (image)
397                 return mono_image_alloc0 (image, size);
398         else
399                 return g_malloc0 (size);
400 }
401
402 #ifndef DISABLE_REFLECTION_EMIT
403 static char*
404 image_strdup (MonoImage *image, const char *s)
405 {
406         MONO_REQ_GC_NEUTRAL_MODE;
407
408         if (image)
409                 return mono_image_strdup (image, s);
410         else
411                 return g_strdup (s);
412 }
413 #endif
414
415 #define image_g_new(image,struct_type, n_structs)               \
416     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
417
418 #define image_g_new0(image,struct_type, n_structs)              \
419     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
420
421
422 static void
423 alloc_table (MonoDynamicTable *table, guint nrows)
424 {
425         MONO_REQ_GC_NEUTRAL_MODE;
426
427         table->rows = nrows;
428         g_assert (table->columns);
429         if (nrows + 1 >= table->alloc_rows) {
430                 while (nrows + 1 >= table->alloc_rows) {
431                         if (table->alloc_rows == 0)
432                                 table->alloc_rows = 16;
433                         else
434                                 table->alloc_rows *= 2;
435                 }
436
437                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
438         }
439 }
440
441 static void
442 make_room_in_stream (MonoDynamicStream *stream, int size)
443 {
444         MONO_REQ_GC_NEUTRAL_MODE;
445
446         if (size <= stream->alloc_size)
447                 return;
448         
449         while (stream->alloc_size <= size) {
450                 if (stream->alloc_size < 4096)
451                         stream->alloc_size = 4096;
452                 else
453                         stream->alloc_size *= 2;
454         }
455         
456         stream->data = g_realloc (stream->data, stream->alloc_size);
457 }
458
459 static guint32
460 string_heap_insert (MonoDynamicStream *sh, const char *str)
461 {
462         MONO_REQ_GC_NEUTRAL_MODE;
463
464         guint32 idx;
465         guint32 len;
466         gpointer oldkey, oldval;
467
468         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
469                 return GPOINTER_TO_UINT (oldval);
470
471         len = strlen (str) + 1;
472         idx = sh->index;
473         
474         make_room_in_stream (sh, idx + len);
475
476         /*
477          * We strdup the string even if we already copy them in sh->data
478          * so that the string pointers in the hash remain valid even if
479          * we need to realloc sh->data. We may want to avoid that later.
480          */
481         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
482         memcpy (sh->data + idx, str, len);
483         sh->index += len;
484         return idx;
485 }
486
487 static guint32
488 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
489 {
490         MONO_REQ_GC_UNSAFE_MODE;
491
492         char *name = mono_string_to_utf8 (str);
493         guint32 idx;
494         idx = string_heap_insert (sh, name);
495         g_free (name);
496         return idx;
497 }
498
499 #ifndef DISABLE_REFLECTION_EMIT
500 static void
501 string_heap_init (MonoDynamicStream *sh)
502 {
503         MONO_REQ_GC_NEUTRAL_MODE;
504
505         sh->index = 0;
506         sh->alloc_size = 4096;
507         sh->data = g_malloc (4096);
508         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
509         string_heap_insert (sh, "");
510 }
511 #endif
512
513 static guint32
514 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
515 {
516         MONO_REQ_GC_NEUTRAL_MODE;
517
518         guint32 idx;
519         
520         make_room_in_stream (stream, stream->index + len);
521         memcpy (stream->data + stream->index, data, len);
522         idx = stream->index;
523         stream->index += len;
524         /* 
525          * align index? Not without adding an additional param that controls it since
526          * we may store a blob value in pieces.
527          */
528         return idx;
529 }
530
531 static guint32
532 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
533 {
534         MONO_REQ_GC_NEUTRAL_MODE;
535
536         guint32 idx;
537         
538         make_room_in_stream (stream, stream->index + len);
539         memset (stream->data + stream->index, 0, len);
540         idx = stream->index;
541         stream->index += len;
542         return idx;
543 }
544
545 static void
546 stream_data_align (MonoDynamicStream *stream)
547 {
548         MONO_REQ_GC_NEUTRAL_MODE;
549
550         char buf [4] = {0};
551         guint32 count = stream->index % 4;
552
553         /* we assume the stream data will be aligned */
554         if (count)
555                 mono_image_add_stream_data (stream, buf, 4 - count);
556 }
557
558 #ifndef DISABLE_REFLECTION_EMIT
559 static int
560 mono_blob_entry_hash (const char* str)
561 {
562         MONO_REQ_GC_NEUTRAL_MODE;
563
564         guint len, h;
565         const char *end;
566         len = mono_metadata_decode_blob_size (str, &str);
567         if (len > 0) {
568                 end = str + len;
569                 h = *str;
570                 for (str += 1; str < end; str++)
571                         h = (h << 5) - h + *str;
572                 return h;
573         } else {
574                 return 0;
575         }
576 }
577
578 static gboolean
579 mono_blob_entry_equal (const char *str1, const char *str2) {
580         MONO_REQ_GC_NEUTRAL_MODE;
581
582         int len, len2;
583         const char *end1;
584         const char *end2;
585         len = mono_metadata_decode_blob_size (str1, &end1);
586         len2 = mono_metadata_decode_blob_size (str2, &end2);
587         if (len != len2)
588                 return 0;
589         return memcmp (end1, end2, len) == 0;
590 }
591 #endif
592 static guint32
593 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
594 {
595         MONO_REQ_GC_NEUTRAL_MODE;
596
597         guint32 idx;
598         char *copy;
599         gpointer oldkey, oldval;
600
601         copy = g_malloc (s1+s2);
602         memcpy (copy, b1, s1);
603         memcpy (copy + s1, b2, s2);
604         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
605                 g_free (copy);
606                 idx = GPOINTER_TO_UINT (oldval);
607         } else {
608                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
609                 mono_image_add_stream_data (&assembly->blob, b2, s2);
610                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
611         }
612         return idx;
613 }
614
615 static guint32
616 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
617 {
618         MONO_REQ_GC_NEUTRAL_MODE;
619
620         char blob_size [8];
621         char *b = blob_size;
622         guint32 size = buf->p - buf->buf;
623         /* store length */
624         g_assert (size <= (buf->end - buf->buf));
625         mono_metadata_encode_value (size, b, &b);
626         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
627 }
628
629 /*
630  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
631  * dest may be misaligned.
632  */
633 static void
634 swap_with_size (char *dest, const char* val, int len, int nelem) {
635         MONO_REQ_GC_NEUTRAL_MODE;
636 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
637         int elem;
638
639         for (elem = 0; elem < nelem; ++elem) {
640                 switch (len) {
641                 case 1:
642                         *dest = *val;
643                         break;
644                 case 2:
645                         dest [0] = val [1];
646                         dest [1] = val [0];
647                         break;
648                 case 4:
649                         dest [0] = val [3];
650                         dest [1] = val [2];
651                         dest [2] = val [1];
652                         dest [3] = val [0];
653                         break;
654                 case 8:
655                         dest [0] = val [7];
656                         dest [1] = val [6];
657                         dest [2] = val [5];
658                         dest [3] = val [4];
659                         dest [4] = val [3];
660                         dest [5] = val [2];
661                         dest [6] = val [1];
662                         dest [7] = val [0];
663                         break;
664                 default:
665                         g_assert_not_reached ();
666                 }
667                 dest += len;
668                 val += len;
669         }
670 #else
671         memcpy (dest, val, len * nelem);
672 #endif
673 }
674
675 static guint32
676 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
677 {
678         MONO_REQ_GC_UNSAFE_MODE;
679         
680         char blob_size [64];
681         char *b = blob_size;
682         guint32 idx = 0, len;
683
684         len = str->length * 2;
685         mono_metadata_encode_value (len, b, &b);
686 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
687         {
688                 char *swapped = g_malloc (2 * mono_string_length (str));
689                 const char *p = (const char*)mono_string_chars (str);
690
691                 swap_with_size (swapped, p, 2, mono_string_length (str));
692                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
693                 g_free (swapped);
694         }
695 #else
696         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
697 #endif
698         return idx;
699 }
700
701 #ifndef DISABLE_REFLECTION_EMIT
702 static MonoClass *
703 default_class_from_mono_type (MonoType *type)
704 {
705         MONO_REQ_GC_NEUTRAL_MODE;
706
707         switch (type->type) {
708         case MONO_TYPE_OBJECT:
709                 return mono_defaults.object_class;
710         case MONO_TYPE_VOID:
711                 return mono_defaults.void_class;
712         case MONO_TYPE_BOOLEAN:
713                 return mono_defaults.boolean_class;
714         case MONO_TYPE_CHAR:
715                 return mono_defaults.char_class;
716         case MONO_TYPE_I1:
717                 return mono_defaults.sbyte_class;
718         case MONO_TYPE_U1:
719                 return mono_defaults.byte_class;
720         case MONO_TYPE_I2:
721                 return mono_defaults.int16_class;
722         case MONO_TYPE_U2:
723                 return mono_defaults.uint16_class;
724         case MONO_TYPE_I4:
725                 return mono_defaults.int32_class;
726         case MONO_TYPE_U4:
727                 return mono_defaults.uint32_class;
728         case MONO_TYPE_I:
729                 return mono_defaults.int_class;
730         case MONO_TYPE_U:
731                 return mono_defaults.uint_class;
732         case MONO_TYPE_I8:
733                 return mono_defaults.int64_class;
734         case MONO_TYPE_U8:
735                 return mono_defaults.uint64_class;
736         case MONO_TYPE_R4:
737                 return mono_defaults.single_class;
738         case MONO_TYPE_R8:
739                 return mono_defaults.double_class;
740         case MONO_TYPE_STRING:
741                 return mono_defaults.string_class;
742         default:
743                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
744                 g_assert_not_reached ();
745         }
746         
747         return NULL;
748 }
749 #endif
750
751 /*
752  * mono_class_get_ref_info:
753  *
754  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
755  */
756 gpointer
757 mono_class_get_ref_info (MonoClass *klass)
758 {
759         MONO_REQ_GC_UNSAFE_MODE;
760
761         if (klass->ref_info_handle == 0)
762                 return NULL;
763         else
764                 return mono_gchandle_get_target (klass->ref_info_handle);
765 }
766
767 void
768 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
769 {
770         MONO_REQ_GC_UNSAFE_MODE;
771
772         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
773         g_assert (klass->ref_info_handle != 0);
774 }
775
776 void
777 mono_class_free_ref_info (MonoClass *klass)
778 {
779         MONO_REQ_GC_NEUTRAL_MODE;
780
781         if (klass->ref_info_handle) {
782                 mono_gchandle_free (klass->ref_info_handle);
783                 klass->ref_info_handle = 0;
784         }
785 }
786
787 static void
788 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
789 {
790         MONO_REQ_GC_NEUTRAL_MODE;
791
792         int i;
793         MonoGenericInst *class_inst;
794         MonoClass *klass;
795
796         g_assert (gclass);
797
798         class_inst = gclass->context.class_inst;
799
800         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
801         klass = gclass->container_class;
802         sigbuffer_add_value (buf, klass->byval_arg.type);
803         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
804
805         sigbuffer_add_value (buf, class_inst->type_argc);
806         for (i = 0; i < class_inst->type_argc; ++i)
807                 encode_type (assembly, class_inst->type_argv [i], buf);
808
809 }
810
811 static void
812 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
813 {
814         MONO_REQ_GC_NEUTRAL_MODE;
815
816         if (!type) {
817                 g_assert_not_reached ();
818                 return;
819         }
820                 
821         if (type->byref)
822                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
823
824         switch (type->type){
825         case MONO_TYPE_VOID:
826         case MONO_TYPE_BOOLEAN:
827         case MONO_TYPE_CHAR:
828         case MONO_TYPE_I1:
829         case MONO_TYPE_U1:
830         case MONO_TYPE_I2:
831         case MONO_TYPE_U2:
832         case MONO_TYPE_I4:
833         case MONO_TYPE_U4:
834         case MONO_TYPE_I8:
835         case MONO_TYPE_U8:
836         case MONO_TYPE_R4:
837         case MONO_TYPE_R8:
838         case MONO_TYPE_I:
839         case MONO_TYPE_U:
840         case MONO_TYPE_STRING:
841         case MONO_TYPE_OBJECT:
842         case MONO_TYPE_TYPEDBYREF:
843                 sigbuffer_add_value (buf, type->type);
844                 break;
845         case MONO_TYPE_PTR:
846                 sigbuffer_add_value (buf, type->type);
847                 encode_type (assembly, type->data.type, buf);
848                 break;
849         case MONO_TYPE_SZARRAY:
850                 sigbuffer_add_value (buf, type->type);
851                 encode_type (assembly, &type->data.klass->byval_arg, buf);
852                 break;
853         case MONO_TYPE_VALUETYPE:
854         case MONO_TYPE_CLASS: {
855                 MonoClass *k = mono_class_from_mono_type (type);
856
857                 if (k->generic_container) {
858                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
859                         encode_generic_class (assembly, gclass, buf);
860                 } else {
861                         /*
862                          * Make sure we use the correct type.
863                          */
864                         sigbuffer_add_value (buf, k->byval_arg.type);
865                         /*
866                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
867                          * otherwise two typerefs could point to the same type, leading to
868                          * verification errors.
869                          */
870                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
871                 }
872                 break;
873         }
874         case MONO_TYPE_ARRAY:
875                 sigbuffer_add_value (buf, type->type);
876                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
877                 sigbuffer_add_value (buf, type->data.array->rank);
878                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
879                 sigbuffer_add_value (buf, 0);
880                 break;
881         case MONO_TYPE_GENERICINST:
882                 encode_generic_class (assembly, type->data.generic_class, buf);
883                 break;
884         case MONO_TYPE_VAR:
885         case MONO_TYPE_MVAR:
886                 sigbuffer_add_value (buf, type->type);
887                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
888                 break;
889         default:
890                 g_error ("need to encode type %x", type->type);
891         }
892 }
893
894 static void
895 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
896 {
897         MONO_REQ_GC_UNSAFE_MODE;
898
899         if (!type) {
900                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
901                 return;
902         }
903
904         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
905 }
906
907 static void
908 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
909 {
910         MONO_REQ_GC_UNSAFE_MODE;
911
912         int i;
913
914         if (modreq) {
915                 for (i = 0; i < mono_array_length (modreq); ++i) {
916                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
917                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
918                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
919                 }
920         }
921         if (modopt) {
922                 for (i = 0; i < mono_array_length (modopt); ++i) {
923                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
924                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
925                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
926                 }
927         }
928 }
929
930 #ifndef DISABLE_REFLECTION_EMIT
931 static guint32
932 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
933 {
934         MONO_REQ_GC_UNSAFE_MODE;
935
936         SigBuffer buf;
937         int i;
938         guint32 nparams =  sig->param_count;
939         guint32 idx;
940
941         if (!assembly->save)
942                 return 0;
943
944         sigbuffer_init (&buf, 32);
945         /*
946          * FIXME: vararg, explicit_this, differenc call_conv values...
947          */
948         idx = sig->call_convention;
949         if (sig->hasthis)
950                 idx |= 0x20; /* hasthis */
951         if (sig->generic_param_count)
952                 idx |= 0x10; /* generic */
953         sigbuffer_add_byte (&buf, idx);
954         if (sig->generic_param_count)
955                 sigbuffer_add_value (&buf, sig->generic_param_count);
956         sigbuffer_add_value (&buf, nparams);
957         encode_type (assembly, sig->ret, &buf);
958         for (i = 0; i < nparams; ++i) {
959                 if (i == sig->sentinelpos)
960                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
961                 encode_type (assembly, sig->params [i], &buf);
962         }
963         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
964         sigbuffer_free (&buf);
965         return idx;
966 }
967 #endif
968
969 static guint32
970 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
971 {
972         MONO_REQ_GC_UNSAFE_MODE;
973
974         /*
975          * FIXME: reuse code from method_encode_signature().
976          */
977         SigBuffer buf;
978         int i;
979         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
980         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
981         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
982         guint32 idx;
983
984         sigbuffer_init (&buf, 32);
985         /* LAMESPEC: all the call conv spec is foobared */
986         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
987         if (mb->call_conv & 2)
988                 idx |= 0x5; /* vararg */
989         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
990                 idx |= 0x20; /* hasthis */
991         if (ngparams)
992                 idx |= 0x10; /* generic */
993         sigbuffer_add_byte (&buf, idx);
994         if (ngparams)
995                 sigbuffer_add_value (&buf, ngparams);
996         sigbuffer_add_value (&buf, nparams + notypes);
997         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
998         encode_reflection_type (assembly, mb->rtype, &buf);
999         for (i = 0; i < nparams; ++i) {
1000                 MonoArray *modreq = NULL;
1001                 MonoArray *modopt = NULL;
1002                 MonoReflectionType *pt;
1003
1004                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1005                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1006                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1007                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1008                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1009                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1010                 encode_reflection_type (assembly, pt, &buf);
1011         }
1012         if (notypes)
1013                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1014         for (i = 0; i < notypes; ++i) {
1015                 MonoReflectionType *pt;
1016
1017                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1018                 encode_reflection_type (assembly, pt, &buf);
1019         }
1020
1021         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1022         sigbuffer_free (&buf);
1023         return idx;
1024 }
1025
1026 static guint32
1027 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1028 {
1029         MONO_REQ_GC_UNSAFE_MODE;
1030
1031         MonoDynamicTable *table;
1032         guint32 *values;
1033         guint32 idx, sig_idx;
1034         guint nl = mono_array_length (ilgen->locals);
1035         SigBuffer buf;
1036         int i;
1037
1038         sigbuffer_init (&buf, 32);
1039         sigbuffer_add_value (&buf, 0x07);
1040         sigbuffer_add_value (&buf, nl);
1041         for (i = 0; i < nl; ++i) {
1042                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1043                 
1044                 if (lb->is_pinned)
1045                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1046                 
1047                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1048         }
1049         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1050         sigbuffer_free (&buf);
1051
1052         if (assembly->standalonesig_cache == NULL)
1053                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1054         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1055         if (idx)
1056                 return idx;
1057
1058         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1059         idx = table->next_idx ++;
1060         table->rows ++;
1061         alloc_table (table, table->rows);
1062         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1063
1064         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1065
1066         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1067
1068         return idx;
1069 }
1070
1071 static guint32
1072 method_count_clauses (MonoReflectionILGen *ilgen)
1073 {
1074         MONO_REQ_GC_UNSAFE_MODE;
1075
1076         guint32 num_clauses = 0;
1077         int i;
1078
1079         MonoILExceptionInfo *ex_info;
1080         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1081                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1082                 if (ex_info->handlers)
1083                         num_clauses += mono_array_length (ex_info->handlers);
1084                 else
1085                         num_clauses++;
1086         }
1087
1088         return num_clauses;
1089 }
1090
1091 #ifndef DISABLE_REFLECTION_EMIT
1092 static MonoExceptionClause*
1093 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1094 {
1095         MONO_REQ_GC_UNSAFE_MODE;
1096
1097         MonoExceptionClause *clauses;
1098         MonoExceptionClause *clause;
1099         MonoILExceptionInfo *ex_info;
1100         MonoILExceptionBlock *ex_block;
1101         guint32 finally_start;
1102         int i, j, clause_index;;
1103
1104         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1105
1106         clause_index = 0;
1107         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1108                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1109                 finally_start = ex_info->start + ex_info->len;
1110                 if (!ex_info->handlers)
1111                         continue;
1112                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1113                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1114                         clause = &(clauses [clause_index]);
1115
1116                         clause->flags = ex_block->type;
1117                         clause->try_offset = ex_info->start;
1118
1119                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1120                                 clause->try_len = finally_start - ex_info->start;
1121                         else
1122                                 clause->try_len = ex_info->len;
1123                         clause->handler_offset = ex_block->start;
1124                         clause->handler_len = ex_block->len;
1125                         if (ex_block->extype) {
1126                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1127                         } else {
1128                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1129                                         clause->data.filter_offset = ex_block->filter_offset;
1130                                 else
1131                                         clause->data.filter_offset = 0;
1132                         }
1133                         finally_start = ex_block->start + ex_block->len;
1134
1135                         clause_index ++;
1136                 }
1137         }
1138
1139         return clauses;
1140 }
1141 #endif /* !DISABLE_REFLECTION_EMIT */
1142
1143 static guint32
1144 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1145 {
1146         MONO_REQ_GC_UNSAFE_MODE;
1147
1148         char flags = 0;
1149         guint32 idx;
1150         guint32 code_size;
1151         gint32 max_stack, i;
1152         gint32 num_locals = 0;
1153         gint32 num_exception = 0;
1154         gint maybe_small;
1155         guint32 fat_flags;
1156         char fat_header [12];
1157         guint32 int_value;
1158         guint16 short_value;
1159         guint32 local_sig = 0;
1160         guint32 header_size = 12;
1161         MonoArray *code;
1162
1163         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1164                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1165                 return 0;
1166
1167         /*if (mb->name)
1168                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1169         if (mb->ilgen) {
1170                 code = mb->ilgen->code;
1171                 code_size = mb->ilgen->code_len;
1172                 max_stack = mb->ilgen->max_stack;
1173                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1174                 if (mb->ilgen->ex_handlers)
1175                         num_exception = method_count_clauses (mb->ilgen);
1176         } else {
1177                 code = mb->code;
1178                 if (code == NULL){
1179                         char *name = mono_string_to_utf8 (mb->name);
1180                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1181                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1182                         g_free (str);
1183                         g_free (name);
1184                         mono_raise_exception (exception);
1185                 }
1186
1187                 code_size = mono_array_length (code);
1188                 max_stack = 8; /* we probably need to run a verifier on the code... */
1189         }
1190
1191         stream_data_align (&assembly->code);
1192
1193         /* check for exceptions, maxstack, locals */
1194         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1195         if (maybe_small) {
1196                 if (code_size < 64 && !(code_size & 1)) {
1197                         flags = (code_size << 2) | 0x2;
1198                 } else if (code_size < 32 && (code_size & 1)) {
1199                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1200                 } else {
1201                         goto fat_header;
1202                 }
1203                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1204                 /* add to the fixup todo list */
1205                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1206                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1207                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1208                 return assembly->text_rva + idx;
1209         } 
1210 fat_header:
1211         if (num_locals)
1212                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1213         /* 
1214          * FIXME: need to set also the header size in fat_flags.
1215          * (and more sects and init locals flags)
1216          */
1217         fat_flags =  0x03;
1218         if (num_exception)
1219                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1220         if (mb->init_locals)
1221                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1222         fat_header [0] = fat_flags;
1223         fat_header [1] = (header_size / 4 ) << 4;
1224         short_value = GUINT16_TO_LE (max_stack);
1225         memcpy (fat_header + 2, &short_value, 2);
1226         int_value = GUINT32_TO_LE (code_size);
1227         memcpy (fat_header + 4, &int_value, 4);
1228         int_value = GUINT32_TO_LE (local_sig);
1229         memcpy (fat_header + 8, &int_value, 4);
1230         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1231         /* add to the fixup todo list */
1232         if (mb->ilgen && mb->ilgen->num_token_fixups)
1233                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1234         
1235         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1236         if (num_exception) {
1237                 unsigned char sheader [4];
1238                 MonoILExceptionInfo * ex_info;
1239                 MonoILExceptionBlock * ex_block;
1240                 int j;
1241
1242                 stream_data_align (&assembly->code);
1243                 /* always use fat format for now */
1244                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1245                 num_exception *= 6 * sizeof (guint32);
1246                 num_exception += 4; /* include the size of the header */
1247                 sheader [1] = num_exception & 0xff;
1248                 sheader [2] = (num_exception >> 8) & 0xff;
1249                 sheader [3] = (num_exception >> 16) & 0xff;
1250                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1251                 /* fat header, so we are already aligned */
1252                 /* reverse order */
1253                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1254                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1255                         if (ex_info->handlers) {
1256                                 int finally_start = ex_info->start + ex_info->len;
1257                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1258                                         guint32 val;
1259                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1260                                         /* the flags */
1261                                         val = GUINT32_TO_LE (ex_block->type);
1262                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1263                                         /* try offset */
1264                                         val = GUINT32_TO_LE (ex_info->start);
1265                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1266                                         /* need fault, too, probably */
1267                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1268                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1269                                         else
1270                                                 val = GUINT32_TO_LE (ex_info->len);
1271                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1272                                         /* handler offset */
1273                                         val = GUINT32_TO_LE (ex_block->start);
1274                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1275                                         /* handler len */
1276                                         val = GUINT32_TO_LE (ex_block->len);
1277                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1278                                         finally_start = ex_block->start + ex_block->len;
1279                                         if (ex_block->extype) {
1280                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1281                                         } else {
1282                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1283                                                         val = ex_block->filter_offset;
1284                                                 else
1285                                                         val = 0;
1286                                         }
1287                                         val = GUINT32_TO_LE (val);
1288                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1289                                         /*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", 
1290                                                         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);*/
1291                                 }
1292                         } else {
1293                                 g_error ("No clauses for ex info block %d", i);
1294                         }
1295                 }
1296         }
1297         return assembly->text_rva + idx;
1298 }
1299
1300 static guint32
1301 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1302 {
1303         MONO_REQ_GC_NEUTRAL_MODE;
1304
1305         int i;
1306         MonoDynamicTable *table;
1307         guint32 *values;
1308         
1309         table = &assembly->tables [table_idx];
1310
1311         g_assert (col < table->columns);
1312
1313         values = table->values + table->columns;
1314         for (i = 1; i <= table->rows; ++i) {
1315                 if (values [col] == token)
1316                         return i;
1317                 values += table->columns;
1318         }
1319         return 0;
1320 }
1321
1322 /*
1323  * LOCKING: Acquires the loader lock. 
1324  */
1325 static MonoCustomAttrInfo*
1326 lookup_custom_attr (MonoImage *image, gpointer member)
1327 {
1328         MONO_REQ_GC_NEUTRAL_MODE;
1329
1330         MonoCustomAttrInfo* res;
1331
1332         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1333
1334         if (!res)
1335                 return NULL;
1336
1337         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1338         res->cached = 0;
1339         return res;
1340 }
1341
1342 static gboolean
1343 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1344 {
1345         MONO_REQ_GC_UNSAFE_MODE;
1346
1347         /* FIXME: Need to do more checks */
1348         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1349                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1350
1351                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1352                         return FALSE;
1353         }
1354
1355         return TRUE;
1356 }
1357
1358 static MonoCustomAttrInfo*
1359 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1360 {
1361         MONO_REQ_GC_UNSAFE_MODE;
1362
1363         int i, index, count, not_visible;
1364         MonoCustomAttrInfo *ainfo;
1365         MonoReflectionCustomAttr *cattr;
1366
1367         if (!cattrs)
1368                 return NULL;
1369         /* FIXME: check in assembly the Run flag is set */
1370
1371         count = mono_array_length (cattrs);
1372
1373         /* Skip nonpublic attributes since MS.NET seems to do the same */
1374         /* FIXME: This needs to be done more globally */
1375         not_visible = 0;
1376         for (i = 0; i < count; ++i) {
1377                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1378                 if (!custom_attr_visible (image, cattr))
1379                         not_visible ++;
1380         }
1381         count -= not_visible;
1382
1383         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1384
1385         ainfo->image = image;
1386         ainfo->num_attrs = count;
1387         ainfo->cached = alloc_img != NULL;
1388         index = 0;
1389         for (i = 0; i < count; ++i) {
1390                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1391                 if (custom_attr_visible (image, cattr)) {
1392                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1393                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1394                         ainfo->attrs [index].ctor = cattr->ctor->method;
1395                         ainfo->attrs [index].data = saved;
1396                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1397                         index ++;
1398                 }
1399         }
1400
1401         return ainfo;
1402 }
1403
1404 #ifndef DISABLE_REFLECTION_EMIT
1405 /*
1406  * LOCKING: Acquires the loader lock. 
1407  */
1408 static void
1409 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1410 {
1411         MONO_REQ_GC_UNSAFE_MODE;
1412
1413         MonoCustomAttrInfo *ainfo, *tmp;
1414
1415         if (!cattrs || !mono_array_length (cattrs))
1416                 return;
1417
1418         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1419
1420         mono_loader_lock ();
1421         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1422         if (tmp)
1423                 mono_custom_attrs_free (tmp);
1424         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1425         mono_loader_unlock ();
1426
1427 }
1428 #endif
1429
1430 void
1431 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1432 {
1433         MONO_REQ_GC_NEUTRAL_MODE;
1434
1435         if (!ainfo->cached)
1436                 g_free (ainfo);
1437 }
1438
1439 /*
1440  * idx is the table index of the object
1441  * type is one of MONO_CUSTOM_ATTR_*
1442  */
1443 static void
1444 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1445 {
1446         MONO_REQ_GC_UNSAFE_MODE;
1447
1448         MonoDynamicTable *table;
1449         MonoReflectionCustomAttr *cattr;
1450         guint32 *values;
1451         guint32 count, i, token;
1452         char blob_size [6];
1453         char *p = blob_size;
1454         
1455         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1456         if (!cattrs)
1457                 return;
1458         count = mono_array_length (cattrs);
1459         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1460         table->rows += count;
1461         alloc_table (table, table->rows);
1462         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1463         idx <<= MONO_CUSTOM_ATTR_BITS;
1464         idx |= type;
1465         for (i = 0; i < count; ++i) {
1466                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1467                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1468                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1469                 type = mono_metadata_token_index (token);
1470                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1471                 switch (mono_metadata_token_table (token)) {
1472                 case MONO_TABLE_METHOD:
1473                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1474                         /*
1475                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1476                          * method, not the one returned by mono_image_create_token ().
1477                          */
1478                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1479                         break;
1480                 case MONO_TABLE_MEMBERREF:
1481                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1482                         break;
1483                 default:
1484                         g_warning ("got wrong token in custom attr");
1485                         continue;
1486                 }
1487                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1488                 p = blob_size;
1489                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1490                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1491                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1492                 values += MONO_CUSTOM_ATTR_SIZE;
1493                 ++table->next_idx;
1494         }
1495 }
1496
1497 static void
1498 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1499 {
1500         MONO_REQ_GC_UNSAFE_MODE;
1501
1502         MonoDynamicTable *table;
1503         guint32 *values;
1504         guint32 count, i, idx;
1505         MonoReflectionPermissionSet *perm;
1506
1507         if (!permissions)
1508                 return;
1509
1510         count = mono_array_length (permissions);
1511         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1512         table->rows += count;
1513         alloc_table (table, table->rows);
1514
1515         for (i = 0; i < mono_array_length (permissions); ++i) {
1516                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1517
1518                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1519
1520                 idx = mono_metadata_token_index (parent_token);
1521                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1522                 switch (mono_metadata_token_table (parent_token)) {
1523                 case MONO_TABLE_TYPEDEF:
1524                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1525                         break;
1526                 case MONO_TABLE_METHOD:
1527                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1528                         break;
1529                 case MONO_TABLE_ASSEMBLY:
1530                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1531                         break;
1532                 default:
1533                         g_assert_not_reached ();
1534                 }
1535
1536                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1537                 values [MONO_DECL_SECURITY_PARENT] = idx;
1538                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1539
1540                 ++table->next_idx;
1541         }
1542 }
1543
1544 /*
1545  * Fill in the MethodDef and ParamDef tables for a method.
1546  * This is used for both normal methods and constructors.
1547  */
1548 static void
1549 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1550 {
1551         MONO_REQ_GC_UNSAFE_MODE;
1552
1553         MonoDynamicTable *table;
1554         guint32 *values;
1555         guint i, count;
1556
1557         /* room in this table is already allocated */
1558         table = &assembly->tables [MONO_TABLE_METHOD];
1559         *mb->table_idx = table->next_idx ++;
1560         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1561         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1562         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1563         values [MONO_METHOD_FLAGS] = mb->attrs;
1564         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1565         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1566         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1567         
1568         table = &assembly->tables [MONO_TABLE_PARAM];
1569         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1570
1571         mono_image_add_decl_security (assembly, 
1572                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1573
1574         if (mb->pinfo) {
1575                 MonoDynamicTable *mtable;
1576                 guint32 *mvalues;
1577                 
1578                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1579                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1580                 
1581                 count = 0;
1582                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1583                         if (mono_array_get (mb->pinfo, gpointer, i))
1584                                 count++;
1585                 }
1586                 table->rows += count;
1587                 alloc_table (table, table->rows);
1588                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1589                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1590                         MonoReflectionParamBuilder *pb;
1591                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1592                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1593                                 values [MONO_PARAM_SEQUENCE] = i;
1594                                 if (pb->name != NULL) {
1595                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1596                                 } else {
1597                                         values [MONO_PARAM_NAME] = 0;
1598                                 }
1599                                 values += MONO_PARAM_SIZE;
1600                                 if (pb->marshal_info) {
1601                                         mtable->rows++;
1602                                         alloc_table (mtable, mtable->rows);
1603                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1604                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1605                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1606                                 }
1607                                 pb->table_idx = table->next_idx++;
1608                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1609                                         guint32 field_type = 0;
1610                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1611                                         mtable->rows ++;
1612                                         alloc_table (mtable, mtable->rows);
1613                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1614                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1615                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1616                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1617                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1618                                 }
1619                         }
1620                 }
1621         }
1622 }
1623
1624 #ifndef DISABLE_REFLECTION_EMIT
1625 static void
1626 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1627 {
1628         MONO_REQ_GC_UNSAFE_MODE;
1629
1630         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1631
1632         rmb->ilgen = mb->ilgen;
1633         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1634         rmb->parameters = mb->parameters;
1635         rmb->generic_params = mb->generic_params;
1636         rmb->generic_container = mb->generic_container;
1637         rmb->opt_types = NULL;
1638         rmb->pinfo = mb->pinfo;
1639         rmb->attrs = mb->attrs;
1640         rmb->iattrs = mb->iattrs;
1641         rmb->call_conv = mb->call_conv;
1642         rmb->code = mb->code;
1643         rmb->type = mb->type;
1644         rmb->name = mb->name;
1645         rmb->table_idx = &mb->table_idx;
1646         rmb->init_locals = mb->init_locals;
1647         rmb->skip_visibility = FALSE;
1648         rmb->return_modreq = mb->return_modreq;
1649         rmb->return_modopt = mb->return_modopt;
1650         rmb->param_modreq = mb->param_modreq;
1651         rmb->param_modopt = mb->param_modopt;
1652         rmb->permissions = mb->permissions;
1653         rmb->mhandle = mb->mhandle;
1654         rmb->nrefs = 0;
1655         rmb->refs = NULL;
1656
1657         if (mb->dll) {
1658                 rmb->charset = mb->charset;
1659                 rmb->extra_flags = mb->extra_flags;
1660                 rmb->native_cc = mb->native_cc;
1661                 rmb->dllentry = mb->dllentry;
1662                 rmb->dll = mb->dll;
1663         }
1664 }
1665
1666 static void
1667 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1668 {
1669         MONO_REQ_GC_UNSAFE_MODE;
1670
1671         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1672
1673         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1674
1675         rmb->ilgen = mb->ilgen;
1676         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1677         rmb->parameters = mb->parameters;
1678         rmb->generic_params = NULL;
1679         rmb->generic_container = NULL;
1680         rmb->opt_types = NULL;
1681         rmb->pinfo = mb->pinfo;
1682         rmb->attrs = mb->attrs;
1683         rmb->iattrs = mb->iattrs;
1684         rmb->call_conv = mb->call_conv;
1685         rmb->code = NULL;
1686         rmb->type = mb->type;
1687         rmb->name = mono_string_new (mono_domain_get (), name);
1688         rmb->table_idx = &mb->table_idx;
1689         rmb->init_locals = mb->init_locals;
1690         rmb->skip_visibility = FALSE;
1691         rmb->return_modreq = NULL;
1692         rmb->return_modopt = NULL;
1693         rmb->param_modreq = mb->param_modreq;
1694         rmb->param_modopt = mb->param_modopt;
1695         rmb->permissions = mb->permissions;
1696         rmb->mhandle = mb->mhandle;
1697         rmb->nrefs = 0;
1698         rmb->refs = NULL;
1699 }
1700
1701 static void
1702 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1703 {
1704         MONO_REQ_GC_UNSAFE_MODE;
1705
1706         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1707
1708         rmb->ilgen = mb->ilgen;
1709         rmb->rtype = mb->rtype;
1710         rmb->parameters = mb->parameters;
1711         rmb->generic_params = NULL;
1712         rmb->generic_container = NULL;
1713         rmb->opt_types = NULL;
1714         rmb->pinfo = NULL;
1715         rmb->attrs = mb->attrs;
1716         rmb->iattrs = 0;
1717         rmb->call_conv = mb->call_conv;
1718         rmb->code = NULL;
1719         rmb->type = (MonoObject *) mb->owner;
1720         rmb->name = mb->name;
1721         rmb->table_idx = NULL;
1722         rmb->init_locals = mb->init_locals;
1723         rmb->skip_visibility = mb->skip_visibility;
1724         rmb->return_modreq = NULL;
1725         rmb->return_modopt = NULL;
1726         rmb->param_modreq = NULL;
1727         rmb->param_modopt = NULL;
1728         rmb->permissions = NULL;
1729         rmb->mhandle = mb->mhandle;
1730         rmb->nrefs = 0;
1731         rmb->refs = NULL;
1732 }       
1733 #endif
1734
1735 static void
1736 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1737 {
1738         MONO_REQ_GC_UNSAFE_MODE;
1739
1740         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1741         MonoDynamicTable *table;
1742         guint32 *values;
1743         guint32 tok;
1744         MonoReflectionMethod *m;
1745         int i;
1746
1747         if (!mb->override_methods)
1748                 return;
1749
1750         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1751                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1752
1753                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1754                 table->rows ++;
1755                 alloc_table (table, table->rows);
1756                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1757                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1758                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1759
1760                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1761                 switch (mono_metadata_token_table (tok)) {
1762                 case MONO_TABLE_MEMBERREF:
1763                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1764                         break;
1765                 case MONO_TABLE_METHOD:
1766                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1767                         break;
1768                 default:
1769                         g_assert_not_reached ();
1770                 }
1771                 values [MONO_METHODIMPL_DECLARATION] = tok;
1772         }
1773 }
1774
1775 #ifndef DISABLE_REFLECTION_EMIT
1776 static void
1777 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1778 {
1779         MONO_REQ_GC_UNSAFE_MODE;
1780
1781         MonoDynamicTable *table;
1782         guint32 *values;
1783         ReflectionMethodBuilder rmb;
1784         int i;
1785
1786         reflection_methodbuilder_from_method_builder (&rmb, mb);
1787
1788         mono_image_basic_method (&rmb, assembly);
1789         mb->table_idx = *rmb.table_idx;
1790
1791         if (mb->dll) { /* It's a P/Invoke method */
1792                 guint32 moduleref;
1793                 /* map CharSet values to on-disk values */
1794                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1795                 int extra_flags = mb->extra_flags;
1796                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1797                 table->rows ++;
1798                 alloc_table (table, table->rows);
1799                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1800                 
1801                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1802                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1803                 if (mb->dllentry)
1804                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1805                 else
1806                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1807                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1808                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1809                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1810                         table->rows ++;
1811                         alloc_table (table, table->rows);
1812                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1813                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1814                 }
1815         }
1816
1817         if (mb->generic_params) {
1818                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1819                 table->rows += mono_array_length (mb->generic_params);
1820                 alloc_table (table, table->rows);
1821                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1822                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1823
1824                         mono_image_get_generic_param_info (
1825                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1826                 }
1827         }
1828
1829 }
1830
1831 static void
1832 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1833 {
1834         MONO_REQ_GC_UNSAFE_MODE;
1835
1836         ReflectionMethodBuilder rmb;
1837
1838         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1839
1840         mono_image_basic_method (&rmb, assembly);
1841         mb->table_idx = *rmb.table_idx;
1842 }
1843 #endif
1844
1845 static char*
1846 type_get_fully_qualified_name (MonoType *type)
1847 {
1848         MONO_REQ_GC_NEUTRAL_MODE;
1849
1850         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1851 }
1852
1853 static char*
1854 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1855 {
1856         MONO_REQ_GC_UNSAFE_MODE;
1857
1858         MonoClass *klass;
1859         MonoAssembly *ta;
1860
1861         klass = mono_class_from_mono_type (type);
1862         if (!klass) 
1863                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1864         ta = klass->image->assembly;
1865         if (assembly_is_dynamic (ta) || (ta == ass)) {
1866                 if (klass->generic_class || klass->generic_container)
1867                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1868                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1869                 else
1870                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1871         }
1872
1873         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1874 }
1875
1876 #ifndef DISABLE_REFLECTION_EMIT
1877 /*field_image is the image to which the eventual custom mods have been encoded against*/
1878 static guint32
1879 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1880 {
1881         MONO_REQ_GC_NEUTRAL_MODE;
1882
1883         SigBuffer buf;
1884         guint32 idx, i, token;
1885
1886         if (!assembly->save)
1887                 return 0;
1888
1889         sigbuffer_init (&buf, 32);
1890         
1891         sigbuffer_add_value (&buf, 0x06);
1892         /* encode custom attributes before the type */
1893         if (type->num_mods) {
1894                 for (i = 0; i < type->num_mods; ++i) {
1895                         if (field_image) {
1896                                 MonoError error;
1897                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1898                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1899
1900                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1901                         } else {
1902                                 token = type->modifiers [i].token;
1903                         }
1904
1905                         if (type->modifiers [i].required)
1906                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1907                         else
1908                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1909
1910                         sigbuffer_add_value (&buf, token);
1911                 }
1912         }
1913         encode_type (assembly, type, &buf);
1914         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1915         sigbuffer_free (&buf);
1916         return idx;
1917 }
1918 #endif
1919
1920 static guint32
1921 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1922 {
1923         MONO_REQ_GC_UNSAFE_MODE;
1924
1925         SigBuffer buf;
1926         guint32 idx;
1927         guint32 typespec = 0;
1928         MonoType *type;
1929         MonoClass *klass;
1930
1931         init_type_builder_generics (fb->type);
1932
1933         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1934         klass = mono_class_from_mono_type (type);
1935
1936         sigbuffer_init (&buf, 32);
1937         
1938         sigbuffer_add_value (&buf, 0x06);
1939         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1940         /* encode custom attributes before the type */
1941
1942         if (klass->generic_container)
1943                 typespec = create_typespec (assembly, type);
1944
1945         if (typespec) {
1946                 MonoGenericClass *gclass;
1947                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1948                 encode_generic_class (assembly, gclass, &buf);
1949         } else {
1950                 encode_type (assembly, type, &buf);
1951         }
1952         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1953         sigbuffer_free (&buf);
1954         return idx;
1955 }
1956
1957 static guint32
1958 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
1959 {
1960         MONO_REQ_GC_UNSAFE_MODE;
1961
1962         char blob_size [64];
1963         char *b = blob_size;
1964         char *box_val;
1965         char* buf;
1966         guint32 idx = 0, len = 0, dummy = 0;
1967
1968         buf = g_malloc (64);
1969         if (!val) {
1970                 *ret_type = MONO_TYPE_CLASS;
1971                 len = 4;
1972                 box_val = (char*)&dummy;
1973         } else {
1974                 box_val = ((char*)val) + sizeof (MonoObject);
1975                 *ret_type = val->vtable->klass->byval_arg.type;
1976         }
1977 handle_enum:
1978         switch (*ret_type) {
1979         case MONO_TYPE_BOOLEAN:
1980         case MONO_TYPE_U1:
1981         case MONO_TYPE_I1:
1982                 len = 1;
1983                 break;
1984         case MONO_TYPE_CHAR:
1985         case MONO_TYPE_U2:
1986         case MONO_TYPE_I2:
1987                 len = 2;
1988                 break;
1989         case MONO_TYPE_U4:
1990         case MONO_TYPE_I4:
1991         case MONO_TYPE_R4:
1992                 len = 4;
1993                 break;
1994         case MONO_TYPE_U8:
1995         case MONO_TYPE_I8:
1996                 len = 8;
1997                 break;
1998         case MONO_TYPE_R8:
1999                 len = 8;
2000                 break;
2001         case MONO_TYPE_VALUETYPE: {
2002                 MonoClass *klass = val->vtable->klass;
2003                 
2004                 if (klass->enumtype) {
2005                         *ret_type = mono_class_enum_basetype (klass)->type;
2006                         goto handle_enum;
2007                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2008                         len = 8;
2009                 } else 
2010                         g_error ("we can't encode valuetypes, we should have never reached this line");
2011                 break;
2012         }
2013         case MONO_TYPE_CLASS:
2014                 break;
2015         case MONO_TYPE_STRING: {
2016                 MonoString *str = (MonoString*)val;
2017                 /* there is no signature */
2018                 len = str->length * 2;
2019                 mono_metadata_encode_value (len, b, &b);
2020 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2021                 {
2022                         char *swapped = g_malloc (2 * mono_string_length (str));
2023                         const char *p = (const char*)mono_string_chars (str);
2024
2025                         swap_with_size (swapped, p, 2, mono_string_length (str));
2026                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2027                         g_free (swapped);
2028                 }
2029 #else
2030                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2031 #endif
2032
2033                 g_free (buf);
2034                 return idx;
2035         }
2036         case MONO_TYPE_GENERICINST:
2037                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2038                 goto handle_enum;
2039         default:
2040                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2041         }
2042
2043         /* there is no signature */
2044         mono_metadata_encode_value (len, b, &b);
2045 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2046         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2047         swap_with_size (blob_size, box_val, len, 1);
2048         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2049 #else
2050         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2051 #endif
2052
2053         g_free (buf);
2054         return idx;
2055 }
2056
2057 static guint32
2058 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2059 {
2060         MONO_REQ_GC_UNSAFE_MODE;
2061
2062         char *str;
2063         SigBuffer buf;
2064         guint32 idx, len;
2065
2066         sigbuffer_init (&buf, 32);
2067
2068         sigbuffer_add_value (&buf, minfo->type);
2069
2070         switch (minfo->type) {
2071         case MONO_NATIVE_BYVALTSTR:
2072         case MONO_NATIVE_BYVALARRAY:
2073                 sigbuffer_add_value (&buf, minfo->count);
2074                 break;
2075         case MONO_NATIVE_LPARRAY:
2076                 if (minfo->eltype || minfo->has_size) {
2077                         sigbuffer_add_value (&buf, minfo->eltype);
2078                         if (minfo->has_size) {
2079                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2080                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2081
2082                                 /* LAMESPEC: ElemMult is undocumented */
2083                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2084                         }
2085                 }
2086                 break;
2087         case MONO_NATIVE_SAFEARRAY:
2088                 if (minfo->eltype)
2089                         sigbuffer_add_value (&buf, minfo->eltype);
2090                 break;
2091         case MONO_NATIVE_CUSTOM:
2092                 if (minfo->guid) {
2093                         str = mono_string_to_utf8 (minfo->guid);
2094                         len = strlen (str);
2095                         sigbuffer_add_value (&buf, len);
2096                         sigbuffer_add_mem (&buf, str, len);
2097                         g_free (str);
2098                 } else {
2099                         sigbuffer_add_value (&buf, 0);
2100                 }
2101                 /* native type name */
2102                 sigbuffer_add_value (&buf, 0);
2103                 /* custom marshaler type name */
2104                 if (minfo->marshaltype || minfo->marshaltyperef) {
2105                         if (minfo->marshaltyperef)
2106                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2107                         else
2108                                 str = mono_string_to_utf8 (minfo->marshaltype);
2109                         len = strlen (str);
2110                         sigbuffer_add_value (&buf, len);
2111                         sigbuffer_add_mem (&buf, str, len);
2112                         g_free (str);
2113                 } else {
2114                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2115                         sigbuffer_add_value (&buf, 0);
2116                 }
2117                 if (minfo->mcookie) {
2118                         str = mono_string_to_utf8 (minfo->mcookie);
2119                         len = strlen (str);
2120                         sigbuffer_add_value (&buf, len);
2121                         sigbuffer_add_mem (&buf, str, len);
2122                         g_free (str);
2123                 } else {
2124                         sigbuffer_add_value (&buf, 0);
2125                 }
2126                 break;
2127         default:
2128                 break;
2129         }
2130         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2131         sigbuffer_free (&buf);
2132         return idx;
2133 }
2134
2135 static void
2136 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2137 {
2138         MONO_REQ_GC_UNSAFE_MODE;
2139
2140         MonoDynamicTable *table;
2141         guint32 *values;
2142
2143         /* maybe this fixup should be done in the C# code */
2144         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2145                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2146         table = &assembly->tables [MONO_TABLE_FIELD];
2147         fb->table_idx = table->next_idx ++;
2148         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2149         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2150         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2151         values [MONO_FIELD_FLAGS] = fb->attrs;
2152         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2153
2154         if (fb->offset != -1) {
2155                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2156                 table->rows ++;
2157                 alloc_table (table, table->rows);
2158                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2159                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2160                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2161         }
2162         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2163                 guint32 field_type = 0;
2164                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2165                 table->rows ++;
2166                 alloc_table (table, table->rows);
2167                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2168                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2169                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2170                 values [MONO_CONSTANT_TYPE] = field_type;
2171                 values [MONO_CONSTANT_PADDING] = 0;
2172         }
2173         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2174                 guint32 rva_idx;
2175                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2176                 table->rows ++;
2177                 alloc_table (table, table->rows);
2178                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2179                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2180                 /*
2181                  * We store it in the code section because it's simpler for now.
2182                  */
2183                 if (fb->rva_data) {
2184                         if (mono_array_length (fb->rva_data) >= 10)
2185                                 stream_data_align (&assembly->code);
2186                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2187                 } else
2188                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2189                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2190         }
2191         if (fb->marshal_info) {
2192                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2193                 table->rows ++;
2194                 alloc_table (table, table->rows);
2195                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2196                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2197                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2198         }
2199 }
2200
2201 static guint32
2202 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2203 {
2204         MONO_REQ_GC_UNSAFE_MODE;
2205
2206         SigBuffer buf;
2207         guint32 nparams = 0;
2208         MonoReflectionMethodBuilder *mb = fb->get_method;
2209         MonoReflectionMethodBuilder *smb = fb->set_method;
2210         guint32 idx, i;
2211
2212         if (mb && mb->parameters)
2213                 nparams = mono_array_length (mb->parameters);
2214         if (!mb && smb && smb->parameters)
2215                 nparams = mono_array_length (smb->parameters) - 1;
2216         sigbuffer_init (&buf, 32);
2217         if (fb->call_conv & 0x20)
2218                 sigbuffer_add_byte (&buf, 0x28);
2219         else
2220                 sigbuffer_add_byte (&buf, 0x08);
2221         sigbuffer_add_value (&buf, nparams);
2222         if (mb) {
2223                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2224                 for (i = 0; i < nparams; ++i) {
2225                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2226                         encode_reflection_type (assembly, pt, &buf);
2227                 }
2228         } else if (smb && smb->parameters) {
2229                 /* the property type is the last param */
2230                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2231                 for (i = 0; i < nparams; ++i) {
2232                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2233                         encode_reflection_type (assembly, pt, &buf);
2234                 }
2235         } else {
2236                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2237         }
2238
2239         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2240         sigbuffer_free (&buf);
2241         return idx;
2242 }
2243
2244 static void
2245 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2246 {
2247         MONO_REQ_GC_UNSAFE_MODE;
2248
2249         MonoDynamicTable *table;
2250         guint32 *values;
2251         guint num_methods = 0;
2252         guint32 semaidx;
2253
2254         /* 
2255          * we need to set things in the following tables:
2256          * PROPERTYMAP (info already filled in _get_type_info ())
2257          * PROPERTY    (rows already preallocated in _get_type_info ())
2258          * METHOD      (method info already done with the generic method code)
2259          * METHODSEMANTICS
2260          * CONSTANT
2261          */
2262         table = &assembly->tables [MONO_TABLE_PROPERTY];
2263         pb->table_idx = table->next_idx ++;
2264         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2265         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2266         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2267         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2268
2269         /* FIXME: we still don't handle 'other' methods */
2270         if (pb->get_method) num_methods ++;
2271         if (pb->set_method) num_methods ++;
2272
2273         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2274         table->rows += num_methods;
2275         alloc_table (table, table->rows);
2276
2277         if (pb->get_method) {
2278                 semaidx = table->next_idx ++;
2279                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2280                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2281                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2282                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2283         }
2284         if (pb->set_method) {
2285                 semaidx = table->next_idx ++;
2286                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2287                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2288                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2289                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2290         }
2291         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2292                 guint32 field_type = 0;
2293                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2294                 table->rows ++;
2295                 alloc_table (table, table->rows);
2296                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2297                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2298                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2299                 values [MONO_CONSTANT_TYPE] = field_type;
2300                 values [MONO_CONSTANT_PADDING] = 0;
2301         }
2302 }
2303
2304 static void
2305 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2306 {
2307         MONO_REQ_GC_UNSAFE_MODE;
2308
2309         MonoDynamicTable *table;
2310         guint32 *values;
2311         guint num_methods = 0;
2312         guint32 semaidx;
2313
2314         /* 
2315          * we need to set things in the following tables:
2316          * EVENTMAP (info already filled in _get_type_info ())
2317          * EVENT    (rows already preallocated in _get_type_info ())
2318          * METHOD      (method info already done with the generic method code)
2319          * METHODSEMANTICS
2320          */
2321         table = &assembly->tables [MONO_TABLE_EVENT];
2322         eb->table_idx = table->next_idx ++;
2323         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2324         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2325         values [MONO_EVENT_FLAGS] = eb->attrs;
2326         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2327
2328         /*
2329          * FIXME: we still don't handle 'other' methods 
2330          */
2331         if (eb->add_method) num_methods ++;
2332         if (eb->remove_method) num_methods ++;
2333         if (eb->raise_method) num_methods ++;
2334
2335         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2336         table->rows += num_methods;
2337         alloc_table (table, table->rows);
2338
2339         if (eb->add_method) {
2340                 semaidx = table->next_idx ++;
2341                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2342                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2343                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2344                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2345         }
2346         if (eb->remove_method) {
2347                 semaidx = table->next_idx ++;
2348                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2349                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2350                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2351                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2352         }
2353         if (eb->raise_method) {
2354                 semaidx = table->next_idx ++;
2355                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2356                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2357                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2358                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2359         }
2360 }
2361
2362 static void
2363 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2364 {
2365         MONO_REQ_GC_UNSAFE_MODE;
2366
2367         MonoDynamicTable *table;
2368         guint32 num_constraints, i;
2369         guint32 *values;
2370         guint32 table_idx;
2371
2372         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2373         num_constraints = gparam->iface_constraints ?
2374                 mono_array_length (gparam->iface_constraints) : 0;
2375         table->rows += num_constraints;
2376         if (gparam->base_type)
2377                 table->rows++;
2378         alloc_table (table, table->rows);
2379
2380         if (gparam->base_type) {
2381                 table_idx = table->next_idx ++;
2382                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2383
2384                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2385                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2386                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2387         }
2388
2389         for (i = 0; i < num_constraints; i++) {
2390                 MonoReflectionType *constraint = mono_array_get (
2391                         gparam->iface_constraints, gpointer, i);
2392
2393                 table_idx = table->next_idx ++;
2394                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2395
2396                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2397                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2398                         assembly, mono_reflection_type_get_handle (constraint));
2399         }
2400 }
2401
2402 static void
2403 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2404 {
2405         MONO_REQ_GC_UNSAFE_MODE;
2406
2407         GenericParamTableEntry *entry;
2408
2409         /*
2410          * The GenericParam table must be sorted according to the `owner' field.
2411          * We need to do this sorting prior to writing the GenericParamConstraint
2412          * table, since we have to use the final GenericParam table indices there
2413          * and they must also be sorted.
2414          */
2415
2416         entry = g_new0 (GenericParamTableEntry, 1);
2417         entry->owner = owner;
2418         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2419         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2420         entry->gparam = gparam;
2421         
2422         g_ptr_array_add (assembly->gen_params, entry);
2423 }
2424
2425 static void
2426 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2427 {
2428         MONO_REQ_GC_UNSAFE_MODE;
2429
2430         MonoDynamicTable *table;
2431         MonoGenericParam *param;
2432         guint32 *values;
2433         guint32 table_idx;
2434
2435         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2436         table_idx = table->next_idx ++;
2437         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2438
2439         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2440
2441         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2442         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2443         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2444         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2445
2446         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2447
2448         encode_constraints (entry->gparam, table_idx, assembly);
2449 }
2450
2451 static guint32
2452 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2453 {
2454         MONO_REQ_GC_UNSAFE_MODE;
2455
2456         MonoDynamicTable *table;
2457         guint32 token;
2458         guint32 *values;
2459         guint32 cols [MONO_ASSEMBLY_SIZE];
2460         const char *pubkey;
2461         guint32 publen;
2462
2463         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2464                 return token;
2465
2466         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2467                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2468                 token = table->next_idx ++;
2469                 table->rows ++;
2470                 alloc_table (table, table->rows);
2471                 values = table->values + token * MONO_MODULEREF_SIZE;
2472                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2473
2474                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2475                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2476                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2477
2478                 return token;
2479         }
2480         
2481         if (assembly_is_dynamic (image->assembly))
2482                 /* FIXME: */
2483                 memset (cols, 0, sizeof (cols));
2484         else {
2485                 /* image->assembly->image is the manifest module */
2486                 image = image->assembly->image;
2487                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2488         }
2489
2490         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2491         token = table->next_idx ++;
2492         table->rows ++;
2493         alloc_table (table, table->rows);
2494         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2495         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2496         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2497         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2498         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2499         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2500         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2501         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2502         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2503
2504         if (strcmp ("", image->assembly->aname.culture)) {
2505                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2506                                 image->assembly->aname.culture);
2507         }
2508
2509         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2510                 guchar pubtoken [9];
2511                 pubtoken [0] = 8;
2512                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2513                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2514         } else {
2515                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2516         }
2517         token <<= MONO_RESOLUTION_SCOPE_BITS;
2518         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2519         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2520         return token;
2521 }
2522
2523 static guint32
2524 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2525 {
2526         MONO_REQ_GC_NEUTRAL_MODE;
2527
2528         MonoDynamicTable *table;
2529         guint32 *values;
2530         guint32 token;
2531         SigBuffer buf;
2532
2533         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2534                 return token;
2535
2536         sigbuffer_init (&buf, 32);
2537         switch (type->type) {
2538         case MONO_TYPE_FNPTR:
2539         case MONO_TYPE_PTR:
2540         case MONO_TYPE_SZARRAY:
2541         case MONO_TYPE_ARRAY:
2542         case MONO_TYPE_VAR:
2543         case MONO_TYPE_MVAR:
2544         case MONO_TYPE_GENERICINST:
2545                 encode_type (assembly, type, &buf);
2546                 break;
2547         case MONO_TYPE_CLASS:
2548         case MONO_TYPE_VALUETYPE: {
2549                 MonoClass *k = mono_class_from_mono_type (type);
2550                 if (!k || !k->generic_container) {
2551                         sigbuffer_free (&buf);
2552                         return 0;
2553                 }
2554                 encode_type (assembly, type, &buf);
2555                 break;
2556         }
2557         default:
2558                 sigbuffer_free (&buf);
2559                 return 0;
2560         }
2561
2562         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2563         if (assembly->save) {
2564                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2565                 alloc_table (table, table->rows + 1);
2566                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2567                 values [MONO_TYPESPEC_SIGNATURE] = token;
2568         }
2569         sigbuffer_free (&buf);
2570
2571         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2572         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2573         table->next_idx ++;
2574         return token;
2575 }
2576
2577 static guint32
2578 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2579 {
2580         MONO_REQ_GC_UNSAFE_MODE;
2581
2582         MonoDynamicTable *table;
2583         guint32 *values;
2584         guint32 token, scope, enclosing;
2585         MonoClass *klass;
2586
2587         /* if the type requires a typespec, we must try that first*/
2588         if (try_typespec && (token = create_typespec (assembly, type)))
2589                 return token;
2590         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2591         if (token)
2592                 return token;
2593         klass = mono_class_from_mono_type (type);
2594         if (!klass)
2595                 klass = mono_class_from_mono_type (type);
2596
2597         /*
2598          * If it's in the same module and not a generic type parameter:
2599          */
2600         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2601                         (type->type != MONO_TYPE_MVAR)) {
2602                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2603                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2604                 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2605                 return token;
2606         }
2607
2608         if (klass->nested_in) {
2609                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2610                 /* get the typeref idx of the enclosing type */
2611                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2612                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2613         } else {
2614                 scope = resolution_scope_from_image (assembly, klass->image);
2615         }
2616         table = &assembly->tables [MONO_TABLE_TYPEREF];
2617         if (assembly->save) {
2618                 alloc_table (table, table->rows + 1);
2619                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2620                 values [MONO_TYPEREF_SCOPE] = scope;
2621                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2622                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2623         }
2624         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2625         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2626         table->next_idx ++;
2627         register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2628         return token;
2629 }
2630
2631 /*
2632  * Despite the name, we handle also TypeSpec (with the above helper).
2633  */
2634 static guint32
2635 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2636 {
2637         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2638 }
2639
2640 #ifndef DISABLE_REFLECTION_EMIT
2641 static guint32
2642 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2643 {
2644         MONO_REQ_GC_NEUTRAL_MODE;
2645
2646         MonoDynamicTable *table;
2647         guint32 *values;
2648         guint32 token, pclass;
2649
2650         switch (parent & MONO_TYPEDEFORREF_MASK) {
2651         case MONO_TYPEDEFORREF_TYPEREF:
2652                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2653                 break;
2654         case MONO_TYPEDEFORREF_TYPESPEC:
2655                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2656                 break;
2657         case MONO_TYPEDEFORREF_TYPEDEF:
2658                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2659                 break;
2660         default:
2661                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2662                 return 0;
2663         }
2664         /* extract the index */
2665         parent >>= MONO_TYPEDEFORREF_BITS;
2666
2667         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2668
2669         if (assembly->save) {
2670                 alloc_table (table, table->rows + 1);
2671                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2672                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2673                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2674                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2675         }
2676
2677         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2678         table->next_idx ++;
2679
2680         return token;
2681 }
2682
2683 /*
2684  * Insert a memberef row into the metadata: the token that point to the memberref
2685  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2686  * mono_image_get_fieldref_token()).
2687  * The sig param is an index to an already built signature.
2688  */
2689 static guint32
2690 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2691 {
2692         MONO_REQ_GC_NEUTRAL_MODE;
2693
2694         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2695         return mono_image_add_memberef_row (assembly, parent, name, sig);
2696 }
2697
2698
2699 static guint32
2700 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2701 {
2702         MONO_REQ_GC_NEUTRAL_MODE;
2703
2704         guint32 token;
2705         MonoMethodSignature *sig;
2706         
2707         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2708
2709         if (create_typespec) {
2710                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2711                 if (token)
2712                         return token;
2713         } 
2714
2715         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2716         if (token && !create_typespec)
2717                 return token;
2718
2719         g_assert (!method->is_inflated);
2720         if (!token) {
2721                 /*
2722                  * A methodref signature can't contain an unmanaged calling convention.
2723                  */
2724                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2725                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2726                         sig->call_convention = MONO_CALL_DEFAULT;
2727                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2728                         method->name,  method_encode_signature (assembly, sig));
2729                 g_free (sig);
2730                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2731         }
2732
2733         if (create_typespec) {
2734                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2735                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2736                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2737
2738                 if (assembly->save) {
2739                         guint32 *values;
2740
2741                         alloc_table (table, table->rows + 1);
2742                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2743                         values [MONO_METHODSPEC_METHOD] = token;
2744                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2745                 }
2746
2747                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2748                 table->next_idx ++;
2749                 /*methodspec and memberef tokens are diferent, */
2750                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2751                 return token;
2752         }
2753         return token;
2754 }
2755
2756 static guint32
2757 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2758 {
2759         guint32 token, parent, sig;
2760         ReflectionMethodBuilder rmb;
2761         char *name;
2762         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2763         
2764         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2765         if (token)
2766                 return token;
2767
2768         name = mono_string_to_utf8 (method->name);
2769         reflection_methodbuilder_from_method_builder (&rmb, method);
2770
2771         /*
2772          * A methodref signature can't contain an unmanaged calling convention.
2773          * Since some flags are encoded as part of call_conv, we need to check against it.
2774         */
2775         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2776                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2777
2778         sig = method_builder_encode_signature (assembly, &rmb);
2779
2780         if (tb->generic_params)
2781                 parent = create_generic_typespec (assembly, tb);
2782         else
2783                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2784
2785         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2786
2787         g_free (name);
2788         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2789         return token;
2790 }
2791
2792 static guint32
2793 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2794                                      const gchar *name, guint32 sig)
2795 {
2796         MonoDynamicTable *table;
2797         guint32 token;
2798         guint32 *values;
2799         
2800         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2801
2802         if (assembly->save) {
2803                 alloc_table (table, table->rows + 1);
2804                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2805                 values [MONO_MEMBERREF_CLASS] = original;
2806                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2807                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2808         }
2809
2810         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2811         table->next_idx ++;
2812
2813         return token;
2814 }
2815
2816 static guint32
2817 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2818 {
2819         SigBuffer buf;
2820         int i;
2821         guint32 nparams = mono_array_length (mb->generic_params);
2822         guint32 idx;
2823
2824         if (!assembly->save)
2825                 return 0;
2826
2827         sigbuffer_init (&buf, 32);
2828
2829         sigbuffer_add_value (&buf, 0xa);
2830         sigbuffer_add_value (&buf, nparams);
2831
2832         for (i = 0; i < nparams; i++) {
2833                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2834                 sigbuffer_add_value (&buf, i);
2835         }
2836
2837         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2838         sigbuffer_free (&buf);
2839         return idx;
2840 }
2841
2842 static guint32
2843 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2844 {
2845         MonoDynamicTable *table;
2846         guint32 *values;
2847         guint32 token, mtoken = 0;
2848
2849         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2850         if (token)
2851                 return token;
2852
2853         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2854
2855         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2856         switch (mono_metadata_token_table (mtoken)) {
2857         case MONO_TABLE_MEMBERREF:
2858                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2859                 break;
2860         case MONO_TABLE_METHOD:
2861                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2862                 break;
2863         default:
2864                 g_assert_not_reached ();
2865         }
2866
2867         if (assembly->save) {
2868                 alloc_table (table, table->rows + 1);
2869                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2870                 values [MONO_METHODSPEC_METHOD] = mtoken;
2871                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2872         }
2873
2874         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2875         table->next_idx ++;
2876
2877         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2878         return token;
2879 }
2880
2881 static guint32
2882 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2883 {
2884         guint32 token;
2885
2886         if (mb->generic_params && create_methodspec) 
2887                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2888
2889         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2890         if (token)
2891                 return token;
2892
2893         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2894         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2895         return token;
2896 }
2897
2898 static guint32
2899 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2900 {
2901         guint32 token, parent, sig;
2902         ReflectionMethodBuilder rmb;
2903         char *name;
2904         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2905         
2906         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2907         if (token)
2908                 return token;
2909
2910         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2911
2912         if (tb->generic_params)
2913                 parent = create_generic_typespec (assembly, tb);
2914         else
2915                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2916         
2917         name = mono_string_to_utf8 (rmb.name);
2918         sig = method_builder_encode_signature (assembly, &rmb);
2919
2920         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2921
2922         g_free (name);
2923         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2924         return token;
2925 }
2926 #endif
2927
2928 static gboolean
2929 is_field_on_inst (MonoClassField *field)
2930 {
2931         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2932 }
2933
2934 /*
2935  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2936  */
2937 static MonoType*
2938 get_field_on_inst_generic_type (MonoClassField *field)
2939 {
2940         MonoClass *klass, *gtd;
2941         MonoDynamicGenericClass *dgclass;
2942         int field_index;
2943
2944         g_assert (is_field_on_inst (field));
2945
2946         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2947
2948         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2949                 field_index = field - dgclass->fields;
2950                 return dgclass->field_generic_types [field_index];              
2951         }
2952
2953         klass = field->parent;
2954         gtd = klass->generic_class->container_class;
2955
2956         if (field >= klass->fields && field - klass->fields < klass->field.count) {
2957                 field_index = field - klass->fields;
2958                 return gtd->fields [field_index].type;
2959         }
2960
2961         g_assert_not_reached ();
2962         return 0;
2963 }
2964
2965 #ifndef DISABLE_REFLECTION_EMIT
2966 static guint32
2967 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2968 {
2969         MonoType *type;
2970         guint32 token;
2971
2972         g_assert (field);
2973         g_assert (field->parent);
2974
2975         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2976         if (token)
2977                 return token;
2978
2979         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2980                 int index = field - field->parent->fields;
2981                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2982         } else {
2983                 if (is_field_on_inst (field))
2984                         type = get_field_on_inst_generic_type (field);
2985                 else
2986                         type = mono_field_get_type (field);
2987         }
2988         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2989                                                                                         mono_field_get_name (field),
2990                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2991         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2992         return token;
2993 }
2994
2995 static guint32
2996 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2997 {
2998         guint32 token;
2999         MonoClass *klass;
3000         MonoGenericClass *gclass;
3001         MonoType *type;
3002         char *name;
3003
3004         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3005         if (token)
3006                 return token;
3007         if (is_sre_field_builder (mono_object_class (f->fb))) {
3008                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3009                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3010                 klass = mono_class_from_mono_type (type);
3011                 gclass = type->data.generic_class;
3012                 g_assert (gclass->is_dynamic);
3013
3014                 name = mono_string_to_utf8 (fb->name);
3015                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3016                                                                                                 field_encode_signature (assembly, fb));
3017                 g_free (name);          
3018         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3019                 guint32 sig;
3020                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3021
3022                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3023                 klass = mono_class_from_mono_type (type);
3024
3025                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3026                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3027         } else {
3028                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3029                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3030         }
3031
3032         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3033         return token;
3034 }
3035
3036 static guint32
3037 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3038 {
3039         guint32 sig, token;
3040         MonoClass *klass;
3041         MonoGenericClass *gclass;
3042         MonoType *type;
3043
3044         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3045
3046         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3047         if (token)
3048                 return token;
3049
3050         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3051                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3052                 ReflectionMethodBuilder rmb;
3053                 char *name;
3054
3055                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3056                 klass = mono_class_from_mono_type (type);
3057
3058                 gclass = type->data.generic_class;
3059                 g_assert (gclass->is_dynamic);
3060
3061                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3062
3063                 name = mono_string_to_utf8 (rmb.name);
3064
3065                 sig = method_builder_encode_signature (assembly, &rmb);
3066
3067                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3068                 g_free (name);
3069         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3070                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3071
3072                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3073                 klass = mono_class_from_mono_type (type);
3074
3075                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3076                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3077         } else {
3078                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3079                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3080         }
3081
3082
3083         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3084         return token;
3085 }
3086
3087 static MonoMethod*
3088 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3089 {
3090         MonoError error;
3091         MonoClass *klass;
3092         MonoGenericContext tmp_context;
3093         MonoType **type_argv;
3094         MonoGenericInst *ginst;
3095         MonoMethod *method, *inflated;
3096         int count, i;
3097
3098         init_type_builder_generics ((MonoObject*)m->inst);
3099
3100         method = inflate_method (m->inst, (MonoObject*)m->mb);
3101
3102         klass = method->klass;
3103
3104         if (m->method_args == NULL)
3105                 return method;
3106
3107         if (method->is_inflated)
3108                 method = ((MonoMethodInflated *) method)->declaring;
3109
3110         count = mono_array_length (m->method_args);
3111
3112         type_argv = g_new0 (MonoType *, count);
3113         for (i = 0; i < count; i++) {
3114                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
3115                 type_argv [i] = mono_reflection_type_get_handle (garg);
3116         }
3117         ginst = mono_metadata_get_generic_inst (count, type_argv);
3118         g_free (type_argv);
3119
3120         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3121         tmp_context.method_inst = ginst;
3122
3123         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3124         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3125         return inflated;
3126 }
3127
3128 static guint32
3129 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3130 {
3131         guint32 sig, token = 0;
3132         MonoType *type;
3133         MonoClass *klass;
3134
3135         if (m->method_args) {
3136                 MonoMethod *inflated;
3137
3138                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3139                 if (create_methodspec)
3140                         token = mono_image_get_methodspec_token (assembly, inflated);
3141                 else
3142                         token = mono_image_get_inflated_method_token (assembly, inflated);
3143                 return token;
3144         }
3145
3146         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3147         if (token)
3148                 return token;
3149
3150         if (is_sre_method_builder (mono_object_class (m->mb))) {
3151                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3152                 MonoGenericClass *gclass;
3153                 ReflectionMethodBuilder rmb;
3154                 char *name;
3155
3156                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3157                 klass = mono_class_from_mono_type (type);
3158                 gclass = type->data.generic_class;
3159                 g_assert (gclass->is_dynamic);
3160
3161                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3162
3163                 name = mono_string_to_utf8 (rmb.name);
3164
3165                 sig = method_builder_encode_signature (assembly, &rmb);
3166
3167                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3168                 g_free (name);          
3169         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3170                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3171
3172                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3173                 klass = mono_class_from_mono_type (type);
3174
3175                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3176                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3177         } else {
3178                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3179                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3180         }
3181
3182         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3183         return token;
3184 }
3185
3186 static guint32
3187 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3188 {
3189         SigBuffer buf;
3190         int i;
3191         guint32 nparams = context->method_inst->type_argc;
3192         guint32 idx;
3193
3194         if (!assembly->save)
3195                 return 0;
3196
3197         sigbuffer_init (&buf, 32);
3198         /*
3199          * FIXME: vararg, explicit_this, differenc call_conv values...
3200          */
3201         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3202         sigbuffer_add_value (&buf, nparams);
3203
3204         for (i = 0; i < nparams; i++)
3205                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3206
3207         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3208         sigbuffer_free (&buf);
3209         return idx;
3210 }
3211
3212 static guint32
3213 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3214 {
3215         MonoDynamicTable *table;
3216         guint32 *values;
3217         guint32 token, mtoken = 0, sig;
3218         MonoMethodInflated *imethod;
3219         MonoMethod *declaring;
3220
3221         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3222
3223         g_assert (method->is_inflated);
3224         imethod = (MonoMethodInflated *) method;
3225         declaring = imethod->declaring;
3226
3227         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3228         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3229
3230         if (!mono_method_signature (declaring)->generic_param_count)
3231                 return mtoken;
3232
3233         switch (mono_metadata_token_table (mtoken)) {
3234         case MONO_TABLE_MEMBERREF:
3235                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3236                 break;
3237         case MONO_TABLE_METHOD:
3238                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3239                 break;
3240         default:
3241                 g_assert_not_reached ();
3242         }
3243
3244         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3245
3246         if (assembly->save) {
3247                 alloc_table (table, table->rows + 1);
3248                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3249                 values [MONO_METHODSPEC_METHOD] = mtoken;
3250                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3251         }
3252
3253         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3254         table->next_idx ++;
3255
3256         return token;
3257 }
3258
3259 static guint32
3260 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3261 {
3262         MonoMethodInflated *imethod;
3263         guint32 token;
3264         
3265         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3266         if (token)
3267                 return token;
3268
3269         g_assert (method->is_inflated);
3270         imethod = (MonoMethodInflated *) method;
3271
3272         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3273                 token = method_encode_methodspec (assembly, method);
3274         } else {
3275                 guint32 sig = method_encode_signature (
3276                         assembly, mono_method_signature (imethod->declaring));
3277                 token = mono_image_get_memberref_token (
3278                         assembly, &method->klass->byval_arg, method->name, sig);
3279         }
3280
3281         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3282         return token;
3283 }
3284
3285 static guint32
3286 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3287 {
3288         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3289         guint32 sig, token;
3290
3291         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3292         token = mono_image_get_memberref_token (
3293                 assembly, &m->klass->byval_arg, m->name, sig);
3294
3295         return token;
3296 }
3297
3298 static guint32
3299 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3300 {
3301         MonoDynamicTable *table;
3302         MonoClass *klass;
3303         MonoType *type;
3304         guint32 *values;
3305         guint32 token;
3306         SigBuffer buf;
3307         int count, i;
3308
3309         /*
3310          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3311          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3312          * Because of this, we must not insert it into the `typeref' hash table.
3313          */
3314         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3315         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3316         if (token)
3317                 return token;
3318
3319         sigbuffer_init (&buf, 32);
3320
3321         g_assert (tb->generic_params);
3322         klass = mono_class_from_mono_type (type);
3323
3324         if (tb->generic_container)
3325                 mono_reflection_create_generic_class (tb);
3326
3327         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3328         g_assert (klass->generic_container);
3329         sigbuffer_add_value (&buf, klass->byval_arg.type);
3330         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3331
3332         count = mono_array_length (tb->generic_params);
3333         sigbuffer_add_value (&buf, count);
3334         for (i = 0; i < count; i++) {
3335                 MonoReflectionGenericParam *gparam;
3336
3337                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3338
3339                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3340         }
3341
3342         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3343
3344         if (assembly->save) {
3345                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3346                 alloc_table (table, table->rows + 1);
3347                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3348                 values [MONO_TYPESPEC_SIGNATURE] = token;
3349         }
3350         sigbuffer_free (&buf);
3351
3352         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3353         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3354         table->next_idx ++;
3355         return token;
3356 }
3357
3358 /*
3359  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3360  */
3361 static MonoType*
3362 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3363 {
3364         int i, count, len, pos;
3365         MonoType *t;
3366
3367         count = 0;
3368         if (modreq)
3369                 count += mono_array_length (modreq);
3370         if (modopt)
3371                 count += mono_array_length (modopt);
3372
3373         if (count == 0)
3374                 return mono_metadata_type_dup (NULL, type);
3375
3376         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3377         t = g_malloc (len);
3378         memcpy (t, type, MONO_SIZEOF_TYPE);
3379
3380         t->num_mods = count;
3381         pos = 0;
3382         if (modreq) {
3383                 for (i = 0; i < mono_array_length (modreq); ++i) {
3384                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3385                         t->modifiers [pos].required = 1;
3386                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3387                         pos ++;
3388                 }
3389         }
3390         if (modopt) {
3391                 for (i = 0; i < mono_array_length (modopt); ++i) {
3392                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3393                         t->modifiers [pos].required = 0;
3394                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3395                         pos ++;
3396                 }
3397         }
3398
3399         return t;
3400 }
3401
3402 static void
3403 init_type_builder_generics (MonoObject *type)
3404 {
3405         MonoReflectionTypeBuilder *tb;
3406
3407         if (!is_sre_type_builder(mono_object_class (type)))
3408                 return;
3409         tb = (MonoReflectionTypeBuilder *)type;
3410
3411         if (tb && tb->generic_container)
3412                 mono_reflection_create_generic_class (tb);
3413 }
3414
3415 static guint32
3416 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3417 {
3418         MonoDynamicTable *table;
3419         MonoType *custom = NULL, *type;
3420         guint32 *values;
3421         guint32 token, pclass, parent, sig;
3422         gchar *name;
3423
3424         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3425         if (token)
3426                 return token;
3427
3428         /* FIXME: is this call necessary? */
3429         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3430         name = mono_string_to_utf8 (fb->name);
3431
3432         /*FIXME this is one more layer of ugliness due how types are created.*/
3433         init_type_builder_generics (fb->type);
3434
3435         /* fb->type does not include the custom modifiers */
3436         /* FIXME: We should do this in one place when a fieldbuilder is created */
3437         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3438         if (fb->modreq || fb->modopt)
3439                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3440
3441         sig = fieldref_encode_signature (assembly, NULL, type);
3442         g_free (custom);
3443
3444         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3445         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3446         
3447         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3448         parent >>= MONO_TYPEDEFORREF_BITS;
3449
3450         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3451
3452         if (assembly->save) {
3453                 alloc_table (table, table->rows + 1);
3454                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3455                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3456                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3457                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3458         }
3459
3460         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3461         table->next_idx ++;
3462         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3463         g_free (name);
3464         return token;
3465 }
3466
3467 static guint32
3468 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3469 {
3470         SigBuffer buf;
3471         guint32 nargs;
3472         guint32 i, idx;
3473
3474         if (!assembly->save)
3475                 return 0;
3476
3477         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3478         g_assert (helper->type == 2);
3479
3480         if (helper->arguments)
3481                 nargs = mono_array_length (helper->arguments);
3482         else
3483                 nargs = 0;
3484
3485         sigbuffer_init (&buf, 32);
3486
3487         /* Encode calling convention */
3488         /* Change Any to Standard */
3489         if ((helper->call_conv & 0x03) == 0x03)
3490                 helper->call_conv = 0x01;
3491         /* explicit_this implies has_this */
3492         if (helper->call_conv & 0x40)
3493                 helper->call_conv &= 0x20;
3494
3495         if (helper->call_conv == 0) { /* Unmanaged */
3496                 idx = helper->unmanaged_call_conv - 1;
3497         } else {
3498                 /* Managed */
3499                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3500                 if (helper->call_conv & 0x02) /* varargs */
3501                         idx += 0x05;
3502         }
3503
3504         sigbuffer_add_byte (&buf, idx);
3505         sigbuffer_add_value (&buf, nargs);
3506         encode_reflection_type (assembly, helper->return_type, &buf);
3507         for (i = 0; i < nargs; ++i) {
3508                 MonoArray *modreqs = NULL;
3509                 MonoArray *modopts = NULL;
3510                 MonoReflectionType *pt;
3511
3512                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3513                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3514                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3515                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3516
3517                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3518                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3519                 encode_reflection_type (assembly, pt, &buf);
3520         }
3521         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3522         sigbuffer_free (&buf);
3523
3524         return idx;
3525 }
3526
3527 static guint32 
3528 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3529 {
3530         guint32 idx;
3531         MonoDynamicTable *table;
3532         guint32 *values;
3533
3534         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3535         idx = table->next_idx ++;
3536         table->rows ++;
3537         alloc_table (table, table->rows);
3538         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3539
3540         values [MONO_STAND_ALONE_SIGNATURE] =
3541                 mono_reflection_encode_sighelper (assembly, helper);
3542
3543         return idx;
3544 }
3545
3546 static int
3547 reflection_cc_to_file (int call_conv) {
3548         switch (call_conv & 0x3) {
3549         case 0:
3550         case 1: return MONO_CALL_DEFAULT;
3551         case 2: return MONO_CALL_VARARG;
3552         default:
3553                 g_assert_not_reached ();
3554         }
3555         return 0;
3556 }
3557 #endif /* !DISABLE_REFLECTION_EMIT */
3558
3559 typedef struct {
3560         MonoType *parent;
3561         MonoMethodSignature *sig;
3562         char *name;
3563         guint32 token;
3564 } ArrayMethod;
3565
3566 #ifndef DISABLE_REFLECTION_EMIT
3567 static guint32
3568 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3569 {
3570         guint32 nparams, i;
3571         GList *tmp;
3572         char *name;
3573         MonoMethodSignature *sig;
3574         ArrayMethod *am;
3575         MonoType *mtype;
3576
3577         name = mono_string_to_utf8 (m->name);
3578         nparams = mono_array_length (m->parameters);
3579         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3580         sig->hasthis = 1;
3581         sig->sentinelpos = -1;
3582         sig->call_convention = reflection_cc_to_file (m->call_conv);
3583         sig->param_count = nparams;
3584         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3585         mtype = mono_reflection_type_get_handle (m->parent);
3586         for (i = 0; i < nparams; ++i)
3587                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3588
3589         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3590                 am = tmp->data;
3591                 if (strcmp (name, am->name) == 0 && 
3592                                 mono_metadata_type_equal (am->parent, mtype) &&
3593                                 mono_metadata_signature_equal (am->sig, sig)) {
3594                         g_free (name);
3595                         g_free (sig);
3596                         m->table_idx = am->token & 0xffffff;
3597                         return am->token;
3598                 }
3599         }
3600         am = g_new0 (ArrayMethod, 1);
3601         am->name = name;
3602         am->sig = sig;
3603         am->parent = mtype;
3604         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3605                 method_encode_signature (assembly, sig));
3606         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3607         m->table_idx = am->token & 0xffffff;
3608         return am->token;
3609 }
3610
3611 /*
3612  * Insert into the metadata tables all the info about the TypeBuilder tb.
3613  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3614  */
3615 static void
3616 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3617 {
3618         MonoDynamicTable *table;
3619         guint *values;
3620         int i, is_object = 0, is_system = 0;
3621         char *n;
3622
3623         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3624         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3625         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3626         n = mono_string_to_utf8 (tb->name);
3627         if (strcmp (n, "Object") == 0)
3628                 is_object++;
3629         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3630         g_free (n);
3631         n = mono_string_to_utf8 (tb->nspace);
3632         if (strcmp (n, "System") == 0)
3633                 is_system++;
3634         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3635         g_free (n);
3636         if (tb->parent && !(is_system && is_object) && 
3637                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3638                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3639         } else {
3640                 values [MONO_TYPEDEF_EXTENDS] = 0;
3641         }
3642         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3643         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3644
3645         /*
3646          * if we have explicitlayout or sequentiallayouts, output data in the
3647          * ClassLayout table.
3648          */
3649         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3650                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3651                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3652                 table->rows++;
3653                 alloc_table (table, table->rows);
3654                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3655                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3656                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3657                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3658         }
3659
3660         /* handle interfaces */
3661         if (tb->interfaces) {
3662                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3663                 i = table->rows;
3664                 table->rows += mono_array_length (tb->interfaces);
3665                 alloc_table (table, table->rows);
3666                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3667                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3668                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3669                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3670                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3671                         values += MONO_INTERFACEIMPL_SIZE;
3672                 }
3673         }
3674
3675         /* handle fields */
3676         if (tb->fields) {
3677                 table = &assembly->tables [MONO_TABLE_FIELD];
3678                 table->rows += tb->num_fields;
3679                 alloc_table (table, table->rows);
3680                 for (i = 0; i < tb->num_fields; ++i)
3681                         mono_image_get_field_info (
3682                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3683         }
3684
3685         /* handle constructors */
3686         if (tb->ctors) {
3687                 table = &assembly->tables [MONO_TABLE_METHOD];
3688                 table->rows += mono_array_length (tb->ctors);
3689                 alloc_table (table, table->rows);
3690                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3691                         mono_image_get_ctor_info (domain,
3692                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3693         }
3694
3695         /* handle methods */
3696         if (tb->methods) {
3697                 table = &assembly->tables [MONO_TABLE_METHOD];
3698                 table->rows += tb->num_methods;
3699                 alloc_table (table, table->rows);
3700                 for (i = 0; i < tb->num_methods; ++i)
3701                         mono_image_get_method_info (
3702                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3703         }
3704
3705         /* Do the same with properties etc.. */
3706         if (tb->events && mono_array_length (tb->events)) {
3707                 table = &assembly->tables [MONO_TABLE_EVENT];
3708                 table->rows += mono_array_length (tb->events);
3709                 alloc_table (table, table->rows);
3710                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3711                 table->rows ++;
3712                 alloc_table (table, table->rows);
3713                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3714                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3715                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3716                 for (i = 0; i < mono_array_length (tb->events); ++i)
3717                         mono_image_get_event_info (
3718                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3719         }
3720         if (tb->properties && mono_array_length (tb->properties)) {
3721                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3722                 table->rows += mono_array_length (tb->properties);
3723                 alloc_table (table, table->rows);
3724                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3725                 table->rows ++;
3726                 alloc_table (table, table->rows);
3727                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3728                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3729                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3730                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3731                         mono_image_get_property_info (
3732                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3733         }
3734
3735         /* handle generic parameters */
3736         if (tb->generic_params) {
3737                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3738                 table->rows += mono_array_length (tb->generic_params);
3739                 alloc_table (table, table->rows);
3740                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3741                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3742
3743                         mono_image_get_generic_param_info (
3744                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3745                 }
3746         }
3747
3748         mono_image_add_decl_security (assembly, 
3749                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3750
3751         if (tb->subtypes) {
3752                 MonoDynamicTable *ntable;
3753                 
3754                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3755                 ntable->rows += mono_array_length (tb->subtypes);
3756                 alloc_table (ntable, ntable->rows);
3757                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3758
3759                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3760                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3761
3762                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3763                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3764                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3765                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3766                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3767                                 ntable->next_idx, ntable->rows);*/
3768                         values += MONO_NESTED_CLASS_SIZE;
3769                         ntable->next_idx++;
3770                 }
3771         }
3772 }
3773 #endif
3774
3775 static void
3776 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3777 {
3778         int i;
3779
3780         mono_ptr_array_append (*types, type);
3781
3782         if (!type->subtypes)
3783                 return;
3784
3785         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3786                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3787                 collect_types (types, subtype);
3788         }
3789 }
3790
3791 static gint
3792 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3793 {
3794         if ((*type1)->table_idx < (*type2)->table_idx)
3795                 return -1;
3796         else
3797                 if ((*type1)->table_idx > (*type2)->table_idx)
3798                         return 1;
3799         else
3800                 return 0;
3801 }
3802
3803 static void
3804 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3805         int i;
3806
3807         if (!pinfo)
3808                 return;
3809         for (i = 0; i < mono_array_length (pinfo); ++i) {
3810                 MonoReflectionParamBuilder *pb;
3811                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3812                 if (!pb)
3813                         continue;
3814                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3815         }
3816 }
3817
3818 static void
3819 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3820         int i;
3821         
3822         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3823         if (tb->fields) {
3824                 for (i = 0; i < tb->num_fields; ++i) {
3825                         MonoReflectionFieldBuilder* fb;
3826                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3827                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3828                 }
3829         }
3830         if (tb->events) {
3831                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3832                         MonoReflectionEventBuilder* eb;
3833                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3834                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3835                 }
3836         }
3837         if (tb->properties) {
3838                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3839                         MonoReflectionPropertyBuilder* pb;
3840                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3841                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3842                 }
3843         }
3844         if (tb->ctors) {
3845                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3846                         MonoReflectionCtorBuilder* cb;
3847                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3848                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3849                         params_add_cattrs (assembly, cb->pinfo);
3850                 }
3851         }
3852
3853         if (tb->methods) {
3854                 for (i = 0; i < tb->num_methods; ++i) {
3855                         MonoReflectionMethodBuilder* mb;
3856                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3857                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3858                         params_add_cattrs (assembly, mb->pinfo);
3859                 }
3860         }
3861
3862         if (tb->subtypes) {
3863                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3864                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3865         }
3866 }
3867
3868 static void
3869 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3870 {
3871         int i;
3872         
3873         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3874
3875         if (moduleb->global_methods) {
3876                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3877                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3878                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3879                         params_add_cattrs (assembly, mb->pinfo);
3880                 }
3881         }
3882
3883         if (moduleb->global_fields) {
3884                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3885                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3886                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3887                 }
3888         }
3889         
3890         if (moduleb->types) {
3891                 for (i = 0; i < moduleb->num_types; ++i)
3892                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3893         }
3894 }
3895
3896 static void
3897 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3898 {
3899         MonoDynamicTable *table;
3900         guint32 *values;
3901         char blob_size [6];
3902         guchar hash [20];
3903         char *b = blob_size;
3904         char *dir, *path;
3905
3906         table = &assembly->tables [MONO_TABLE_FILE];
3907         table->rows++;
3908         alloc_table (table, table->rows);
3909         values = table->values + table->next_idx * MONO_FILE_SIZE;
3910         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3911         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3912         if (image_is_dynamic (module->image)) {
3913                 /* This depends on the fact that the main module is emitted last */
3914                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3915                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3916         } else {
3917                 dir = NULL;
3918                 path = g_strdup (module->image->name);
3919         }
3920         mono_sha1_get_digest_from_file (path, hash);
3921         g_free (dir);
3922         g_free (path);
3923         mono_metadata_encode_value (20, b, &b);
3924         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3925         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3926         table->next_idx ++;
3927 }
3928
3929 static void
3930 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3931 {
3932         MonoDynamicTable *table;
3933         int i;
3934
3935         table = &assembly->tables [MONO_TABLE_MODULE];
3936         mb->table_idx = table->next_idx ++;
3937         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3938         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3939         i /= 16;
3940         ++i;
3941         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3942         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3943         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3944         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3945 }
3946
3947 static guint32
3948 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3949         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3950 {
3951         MonoDynamicTable *table;
3952         guint32 *values;
3953         guint32 visib, res;
3954
3955         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3956         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3957                 return 0;
3958
3959         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3960         table->rows++;
3961         alloc_table (table, table->rows);
3962         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3963
3964         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3965         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3966         if (klass->nested_in)
3967                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3968         else
3969                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3970         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3971         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3972
3973         res = table->next_idx;
3974
3975         table->next_idx ++;
3976
3977         /* Emit nested types */
3978         if (klass->ext && klass->ext->nested_classes) {
3979                 GList *tmp;
3980
3981                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3982                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3983         }
3984
3985         return res;
3986 }
3987
3988 static void
3989 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3990         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3991 {
3992         MonoClass *klass;
3993         guint32 idx, i;
3994
3995         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3996
3997         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3998
3999         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4000                                                                                                    parent_index, assembly);
4001
4002         /* 
4003          * Emit nested types
4004          * We need to do this ourselves since klass->nested_classes is not set up.
4005          */
4006         if (tb->subtypes) {
4007                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4008                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4009         }
4010 }
4011
4012 static void
4013 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4014         guint32 module_index, MonoDynamicImage *assembly)
4015 {
4016         MonoImage *image = module->image;
4017         MonoTableInfo  *t;
4018         guint32 i;
4019
4020         t = &image->tables [MONO_TABLE_TYPEDEF];
4021
4022         for (i = 0; i < t->rows; ++i) {
4023                 MonoError error;
4024                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4025                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4026
4027                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4028                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4029         }
4030 }
4031
4032 static void
4033 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4034 {
4035         MonoDynamicTable *table;
4036         guint32 *values;
4037         guint32 scope, scope_idx, impl, current_idx;
4038         gboolean forwarder = TRUE;
4039         gpointer iter = NULL;
4040         MonoClass *nested;
4041
4042         if (klass->nested_in) {
4043                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4044                 forwarder = FALSE;
4045         } else {
4046                 scope = resolution_scope_from_image (assembly, klass->image);
4047                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4048                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4049                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4050         }
4051
4052         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4053
4054         table->rows++;
4055         alloc_table (table, table->rows);
4056         current_idx = table->next_idx;
4057         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4058
4059         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4060         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4061         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4062         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4063         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4064
4065         table->next_idx++;
4066
4067         while ((nested = mono_class_get_nested_types (klass, &iter)))
4068                 add_exported_type (assemblyb, assembly, nested, current_idx);
4069 }
4070
4071 static void
4072 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4073 {
4074         MonoClass *klass;
4075         int i;
4076
4077         if (!assemblyb->type_forwarders)
4078                 return;
4079
4080         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4081                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4082                 MonoType *type;
4083                 if (!t)
4084                         continue;
4085
4086                 type = mono_reflection_type_get_handle (t);
4087                 g_assert (type);
4088
4089                 klass = mono_class_from_mono_type (type);
4090
4091                 add_exported_type (assemblyb, assembly, klass, 0);
4092         }
4093 }
4094
4095 #define align_pointer(base,p)\
4096         do {\
4097                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4098                 if (__diff & 3)\
4099                         (p) += 4 - (__diff & 3);\
4100         } while (0)
4101
4102 static int
4103 compare_constants (const void *a, const void *b)
4104 {
4105         const guint32 *a_values = a;
4106         const guint32 *b_values = b;
4107         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4108 }
4109
4110 static int
4111 compare_semantics (const void *a, const void *b)
4112 {
4113         const guint32 *a_values = a;
4114         const guint32 *b_values = b;
4115         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4116         if (assoc)
4117                 return assoc;
4118         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4119 }
4120
4121 static int
4122 compare_custom_attrs (const void *a, const void *b)
4123 {
4124         const guint32 *a_values = a;
4125         const guint32 *b_values = b;
4126
4127         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4128 }
4129
4130 static int
4131 compare_field_marshal (const void *a, const void *b)
4132 {
4133         const guint32 *a_values = a;
4134         const guint32 *b_values = b;
4135
4136         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4137 }
4138
4139 static int
4140 compare_nested (const void *a, const void *b)
4141 {
4142         const guint32 *a_values = a;
4143         const guint32 *b_values = b;
4144
4145         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4146 }
4147
4148 static int
4149 compare_genericparam (const void *a, const void *b)
4150 {
4151         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4152         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4153
4154         if ((*b_entry)->owner == (*a_entry)->owner)
4155                 return 
4156                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4157                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4158         else
4159                 return (*a_entry)->owner - (*b_entry)->owner;
4160 }
4161
4162 static int
4163 compare_declsecurity_attrs (const void *a, const void *b)
4164 {
4165         const guint32 *a_values = a;
4166         const guint32 *b_values = b;
4167
4168         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4169 }
4170
4171 static int
4172 compare_interface_impl (const void *a, const void *b)
4173 {
4174         const guint32 *a_values = a;
4175         const guint32 *b_values = b;
4176
4177         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4178         if (klass)
4179                 return klass;
4180
4181         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4182 }
4183
4184 static void
4185 pad_heap (MonoDynamicStream *sh)
4186 {
4187         if (sh->index & 3) {
4188                 int sz = 4 - (sh->index & 3);
4189                 memset (sh->data + sh->index, 0, sz);
4190                 sh->index += sz;
4191         }
4192 }
4193
4194 struct StreamDesc {
4195         const char *name;
4196         MonoDynamicStream *stream;
4197 };
4198
4199 /*
4200  * build_compressed_metadata() fills in the blob of data that represents the 
4201  * raw metadata as it will be saved in the PE file. The five streams are output 
4202  * and the metadata tables are comnpressed from the guint32 array representation, 
4203  * to the compressed on-disk format.
4204  */
4205 static void
4206 build_compressed_metadata (MonoDynamicImage *assembly)
4207 {
4208         MonoDynamicTable *table;
4209         int i;
4210         guint64 valid_mask = 0;
4211         guint64 sorted_mask;
4212         guint32 heapt_size = 0;
4213         guint32 meta_size = 256; /* allow for header and other stuff */
4214         guint32 table_offset;
4215         guint32 ntables = 0;
4216         guint64 *int64val;
4217         guint32 *int32val;
4218         guint16 *int16val;
4219         MonoImage *meta;
4220         unsigned char *p;
4221         struct StreamDesc stream_desc [5];
4222
4223         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4224         for (i = 0; i < assembly->gen_params->len; i++){
4225                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4226                 write_generic_param_entry (assembly, entry);
4227         }
4228
4229         stream_desc [0].name  = "#~";
4230         stream_desc [0].stream = &assembly->tstream;
4231         stream_desc [1].name  = "#Strings";
4232         stream_desc [1].stream = &assembly->sheap;
4233         stream_desc [2].name  = "#US";
4234         stream_desc [2].stream = &assembly->us;
4235         stream_desc [3].name  = "#Blob";
4236         stream_desc [3].stream = &assembly->blob;
4237         stream_desc [4].name  = "#GUID";
4238         stream_desc [4].stream = &assembly->guid;
4239         
4240         /* tables that are sorted */
4241         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4242                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4243                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4244                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4245                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4246                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4247                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4248         
4249         /* Compute table sizes */
4250         /* the MonoImage has already been created in mono_image_basic_init() */
4251         meta = &assembly->image;
4252
4253         /* sizes should be multiple of 4 */
4254         pad_heap (&assembly->blob);
4255         pad_heap (&assembly->guid);
4256         pad_heap (&assembly->sheap);
4257         pad_heap (&assembly->us);
4258
4259         /* Setup the info used by compute_sizes () */
4260         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4261         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4262         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4263
4264         meta_size += assembly->blob.index;
4265         meta_size += assembly->guid.index;
4266         meta_size += assembly->sheap.index;
4267         meta_size += assembly->us.index;
4268
4269         for (i=0; i < MONO_TABLE_NUM; ++i)
4270                 meta->tables [i].rows = assembly->tables [i].rows;
4271         
4272         for (i = 0; i < MONO_TABLE_NUM; i++){
4273                 if (meta->tables [i].rows == 0)
4274                         continue;
4275                 valid_mask |= (guint64)1 << i;
4276                 ntables ++;
4277                 meta->tables [i].row_size = mono_metadata_compute_size (
4278                         meta, i, &meta->tables [i].size_bitfield);
4279                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4280         }
4281         heapt_size += 24; /* #~ header size */
4282         heapt_size += ntables * 4;
4283         /* make multiple of 4 */
4284         heapt_size += 3;
4285         heapt_size &= ~3;
4286         meta_size += heapt_size;
4287         meta->raw_metadata = g_malloc0 (meta_size);
4288         p = (unsigned char*)meta->raw_metadata;
4289         /* the metadata signature */
4290         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4291         /* version numbers and 4 bytes reserved */
4292         int16val = (guint16*)p;
4293         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4294         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4295         p += 8;
4296         /* version string */
4297         int32val = (guint32*)p;
4298         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4299         p += 4;
4300         memcpy (p, meta->version, strlen (meta->version));
4301         p += GUINT32_FROM_LE (*int32val);
4302         align_pointer (meta->raw_metadata, p);
4303         int16val = (guint16*)p;
4304         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4305         *int16val = GUINT16_TO_LE (5); /* number of streams */
4306         p += 4;
4307
4308         /*
4309          * write the stream info.
4310          */
4311         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4312         table_offset += 3; table_offset &= ~3;
4313
4314         assembly->tstream.index = heapt_size;
4315         for (i = 0; i < 5; ++i) {
4316                 int32val = (guint32*)p;
4317                 stream_desc [i].stream->offset = table_offset;
4318                 *int32val++ = GUINT32_TO_LE (table_offset);
4319                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4320                 table_offset += GUINT32_FROM_LE (*int32val);
4321                 table_offset += 3; table_offset &= ~3;
4322                 p += 8;
4323                 strcpy ((char*)p, stream_desc [i].name);
4324                 p += strlen (stream_desc [i].name) + 1;
4325                 align_pointer (meta->raw_metadata, p);
4326         }
4327         /* 
4328          * now copy the data, the table stream header and contents goes first.
4329          */
4330         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4331         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4332         int32val = (guint32*)p;
4333         *int32val = GUINT32_TO_LE (0); /* reserved */
4334         p += 4;
4335
4336         *p++ = 2; /* version */
4337         *p++ = 0;
4338
4339         if (meta->idx_string_wide)
4340                 *p |= 0x01;
4341         if (meta->idx_guid_wide)
4342                 *p |= 0x02;
4343         if (meta->idx_blob_wide)
4344                 *p |= 0x04;
4345         ++p;
4346         *p++ = 1; /* reserved */
4347         int64val = (guint64*)p;
4348         *int64val++ = GUINT64_TO_LE (valid_mask);
4349         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4350         p += 16;
4351         int32val = (guint32*)p;
4352         for (i = 0; i < MONO_TABLE_NUM; i++){
4353                 if (meta->tables [i].rows == 0)
4354                         continue;
4355                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4356         }
4357         p = (unsigned char*)int32val;
4358
4359         /* sort the tables that still need sorting */
4360         table = &assembly->tables [MONO_TABLE_CONSTANT];
4361         if (table->rows)
4362                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4363         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4364         if (table->rows)
4365                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4366         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4367         if (table->rows)
4368                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4369         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4370         if (table->rows)
4371                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4372         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4373         if (table->rows)
4374                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4375         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4376         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4377         if (table->rows)
4378                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4379         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4380         if (table->rows)
4381                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4382
4383         /* compress the tables */
4384         for (i = 0; i < MONO_TABLE_NUM; i++){
4385                 int row, col;
4386                 guint32 *values;
4387                 guint32 bitfield = meta->tables [i].size_bitfield;
4388                 if (!meta->tables [i].rows)
4389                         continue;
4390                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4391                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4392                 meta->tables [i].base = (char*)p;
4393                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4394                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4395                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4396                                 switch (mono_metadata_table_size (bitfield, col)) {
4397                                 case 1:
4398                                         *p++ = values [col];
4399                                         break;
4400                                 case 2:
4401                                         *p++ = values [col] & 0xff;
4402                                         *p++ = (values [col] >> 8) & 0xff;
4403                                         break;
4404                                 case 4:
4405                                         *p++ = values [col] & 0xff;
4406                                         *p++ = (values [col] >> 8) & 0xff;
4407                                         *p++ = (values [col] >> 16) & 0xff;
4408                                         *p++ = (values [col] >> 24) & 0xff;
4409                                         break;
4410                                 default:
4411                                         g_assert_not_reached ();
4412                                 }
4413                         }
4414                 }
4415                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4416         }
4417         
4418         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4419         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4420         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4421         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4422         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4423
4424         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4425 }
4426
4427 /*
4428  * Some tables in metadata need to be sorted according to some criteria, but
4429  * when methods and fields are first created with reflection, they may be assigned a token
4430  * that doesn't correspond to the final token they will get assigned after the sorting.
4431  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4432  * with the reflection objects that represent them. Once all the tables are set up, the 
4433  * reflection objects will contains the correct table index. fixup_method() will fixup the
4434  * tokens for the method with ILGenerator @ilgen.
4435  */
4436 static void
4437 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4438 {
4439         guint32 code_idx = GPOINTER_TO_UINT (value);
4440         MonoReflectionILTokenInfo *iltoken;
4441         MonoReflectionFieldBuilder *field;
4442         MonoReflectionCtorBuilder *ctor;
4443         MonoReflectionMethodBuilder *method;
4444         MonoReflectionTypeBuilder *tb;
4445         MonoReflectionArrayMethod *am;
4446         guint32 i, idx = 0;
4447         unsigned char *target;
4448
4449         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4450                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4451                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4452                 switch (target [3]) {
4453                 case MONO_TABLE_FIELD:
4454                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4455                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4456                                 idx = field->table_idx;
4457                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4458                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4459                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4460                         } else {
4461                                 g_assert_not_reached ();
4462                         }
4463                         break;
4464                 case MONO_TABLE_METHOD:
4465                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4466                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4467                                 idx = method->table_idx;
4468                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4469                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4470                                 idx = ctor->table_idx;
4471                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4472                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4473                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4474                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4475                         } else {
4476                                 g_assert_not_reached ();
4477                         }
4478                         break;
4479                 case MONO_TABLE_TYPEDEF:
4480                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4481                                 g_assert_not_reached ();
4482                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4483                         idx = tb->table_idx;
4484                         break;
4485                 case MONO_TABLE_MEMBERREF:
4486                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4487                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4488                                 idx = am->table_idx;
4489                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4490                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4491                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4492                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4493                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4494                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4495                                 continue;
4496                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4497                                 continue;
4498                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4499                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4500                                 g_assert (is_field_on_inst (f));
4501                                 continue;
4502                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4503                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4504                                 continue;
4505                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4506                                 continue;
4507                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4508                                 continue;
4509                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4510                                 continue;
4511                         } else {
4512                                 g_assert_not_reached ();
4513                         }
4514                         break;
4515                 case MONO_TABLE_METHODSPEC:
4516                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4517                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4518                                 g_assert (mono_method_signature (m)->generic_param_count);
4519                                 continue;
4520                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4521                                 continue;
4522                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4523                                 continue;
4524                         } else {
4525                                 g_assert_not_reached ();
4526                         }
4527                         break;
4528                 default:
4529                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4530                 }
4531                 target [0] = idx & 0xff;
4532                 target [1] = (idx >> 8) & 0xff;
4533                 target [2] = (idx >> 16) & 0xff;
4534         }
4535 }
4536
4537 /*
4538  * fixup_cattrs:
4539  *
4540  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4541  * value is not known when the table is emitted.
4542  */
4543 static void
4544 fixup_cattrs (MonoDynamicImage *assembly)
4545 {
4546         MonoDynamicTable *table;
4547         guint32 *values;
4548         guint32 type, i, idx, token;
4549         MonoObject *ctor;
4550
4551         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4552
4553         for (i = 0; i < table->rows; ++i) {
4554                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4555
4556                 type = values [MONO_CUSTOM_ATTR_TYPE];
4557                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4558                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4559                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4560                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4561                         g_assert (ctor);
4562
4563                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4564                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4565                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4566                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4567                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4568                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4569                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4570                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4571                         }
4572                 }
4573         }
4574 }
4575
4576 static void
4577 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4578 {
4579         MonoDynamicTable *table;
4580         guint32 *values;
4581
4582         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4583         table->rows++;
4584         alloc_table (table, table->rows);
4585         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4586         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4587         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4588         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4589         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4590         table->next_idx++;
4591 }
4592
4593 static void
4594 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4595 {
4596         MonoDynamicTable *table;
4597         guint32 *values;
4598         char blob_size [6];
4599         guchar hash [20];
4600         char *b = blob_size;
4601         char *name, *sname;
4602         guint32 idx, offset;
4603
4604         if (rsrc->filename) {
4605                 name = mono_string_to_utf8 (rsrc->filename);
4606                 sname = g_path_get_basename (name);
4607         
4608                 table = &assembly->tables [MONO_TABLE_FILE];
4609                 table->rows++;
4610                 alloc_table (table, table->rows);
4611                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4612                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4613                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4614                 g_free (sname);
4615
4616                 mono_sha1_get_digest_from_file (name, hash);
4617                 mono_metadata_encode_value (20, b, &b);
4618                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4619                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4620                 g_free (name);
4621                 idx = table->next_idx++;
4622                 rsrc->offset = 0;
4623                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4624         } else {
4625                 char sizebuf [4];
4626                 char *data;
4627                 guint len;
4628                 if (rsrc->data) {
4629                         data = mono_array_addr (rsrc->data, char, 0);
4630                         len = mono_array_length (rsrc->data);
4631                 } else {
4632                         data = NULL;
4633                         len = 0;
4634                 }
4635                 offset = len;
4636                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4637                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4638                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4639                 mono_image_add_stream_data (&assembly->resources, data, len);
4640
4641                 if (!mb->is_main)
4642                         /* 
4643                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4644                          * the main module, but that needs to reference the FILE table
4645                          * which isn't emitted yet.
4646                          */
4647                         return;
4648                 else
4649                         idx = 0;
4650         }
4651
4652         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4653 }
4654
4655 static void
4656 set_version_from_string (MonoString *version, guint32 *values)
4657 {
4658         gchar *ver, *p, *str;
4659         guint32 i;
4660         
4661         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4662         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4663         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4664         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4665         if (!version)
4666                 return;
4667         ver = str = mono_string_to_utf8 (version);
4668         for (i = 0; i < 4; ++i) {
4669                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4670                 switch (*p) {
4671                 case '.':
4672                         p++;
4673                         break;
4674                 case '*':
4675                         /* handle Revision and Build */
4676                         p++;
4677                         break;
4678                 }
4679                 ver = p;
4680         }
4681         g_free (str);
4682 }
4683
4684 static guint32
4685 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4686         gsize len;
4687         guint32 token = 0;
4688         char blob_size [6];
4689         char *b = blob_size;
4690
4691         if (!pkey)
4692                 return token;
4693
4694         len = mono_array_length (pkey);
4695         mono_metadata_encode_value (len, b, &b);
4696         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4697         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4698
4699         assembly->public_key = g_malloc (len);
4700         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4701         assembly->public_key_len = len;
4702
4703         /* Special case: check for ECMA key (16 bytes) */
4704         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4705                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4706                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4707         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4708                 /* minimum key size (in 2.0) is 384 bits */
4709                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4710         } else {
4711                 /* FIXME - verifier */
4712                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4713                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4714         }
4715         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4716
4717         return token;
4718 }
4719
4720 static void
4721 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4722 {
4723         MonoDynamicTable *table;
4724         MonoDynamicImage *assembly;
4725         MonoReflectionAssemblyBuilder *assemblyb;
4726         MonoDomain *domain;
4727         guint32 *values;
4728         int i;
4729         guint32 module_index;
4730
4731         assemblyb = moduleb->assemblyb;
4732         assembly = moduleb->dynamic_image;
4733         domain = mono_object_domain (assemblyb);
4734
4735         /* Emit ASSEMBLY table */
4736         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4737         alloc_table (table, 1);
4738         values = table->values + MONO_ASSEMBLY_SIZE;
4739         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4740         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4741         if (assemblyb->culture) {
4742                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4743         } else {
4744                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4745         }
4746         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4747         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4748         set_version_from_string (assemblyb->version, values);
4749
4750         /* Emit FILE + EXPORTED_TYPE table */
4751         module_index = 0;
4752         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4753                 int j;
4754                 MonoReflectionModuleBuilder *file_module = 
4755                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4756                 if (file_module != moduleb) {
4757                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4758                         module_index ++;
4759                         if (file_module->types) {
4760                                 for (j = 0; j < file_module->num_types; ++j) {
4761                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4762                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4763                                 }
4764                         }
4765                 }
4766         }
4767         if (assemblyb->loaded_modules) {
4768                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4769                         MonoReflectionModule *file_module = 
4770                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4771                         mono_image_fill_file_table (domain, file_module, assembly);
4772                         module_index ++;
4773                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4774                 }
4775         }
4776         if (assemblyb->type_forwarders)
4777                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4778
4779         /* Emit MANIFESTRESOURCE table */
4780         module_index = 0;
4781         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4782                 int j;
4783                 MonoReflectionModuleBuilder *file_module = 
4784                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4785                 /* The table for the main module is emitted later */
4786                 if (file_module != moduleb) {
4787                         module_index ++;
4788                         if (file_module->resources) {
4789                                 int len = mono_array_length (file_module->resources);
4790                                 for (j = 0; j < len; ++j) {
4791                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4792                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4793                                 }
4794                         }
4795                 }
4796         }               
4797 }
4798
4799 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4800
4801 /*
4802  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4803  * for the modulebuilder @moduleb.
4804  * At the end of the process, method and field tokens are fixed up and the 
4805  * on-disk compressed metadata representation is created.
4806  */
4807 void
4808 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4809 {
4810         MonoDynamicTable *table;
4811         MonoDynamicImage *assembly;
4812         MonoReflectionAssemblyBuilder *assemblyb;
4813         MonoDomain *domain;
4814         MonoPtrArray types;
4815         guint32 *values;
4816         int i, j;
4817
4818         assemblyb = moduleb->assemblyb;
4819         assembly = moduleb->dynamic_image;
4820         domain = mono_object_domain (assemblyb);
4821
4822         if (assembly->text_rva)
4823                 return;
4824
4825         assembly->text_rva = START_TEXT_RVA;
4826
4827         if (moduleb->is_main) {
4828                 mono_image_emit_manifest (moduleb);
4829         }
4830
4831         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4832         table->rows = 1; /* .<Module> */
4833         table->next_idx++;
4834         alloc_table (table, table->rows);
4835         /*
4836          * Set the first entry.
4837          */
4838         values = table->values + table->columns;
4839         values [MONO_TYPEDEF_FLAGS] = 0;
4840         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4841         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4842         values [MONO_TYPEDEF_EXTENDS] = 0;
4843         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4844         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4845
4846         /* 
4847          * handle global methods 
4848          * FIXME: test what to do when global methods are defined in multiple modules.
4849          */
4850         if (moduleb->global_methods) {
4851                 table = &assembly->tables [MONO_TABLE_METHOD];
4852                 table->rows += mono_array_length (moduleb->global_methods);
4853                 alloc_table (table, table->rows);
4854                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4855                         mono_image_get_method_info (
4856                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4857         }
4858         if (moduleb->global_fields) {
4859                 table = &assembly->tables [MONO_TABLE_FIELD];
4860                 table->rows += mono_array_length (moduleb->global_fields);
4861                 alloc_table (table, table->rows);
4862                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4863                         mono_image_get_field_info (
4864                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4865         }
4866
4867         table = &assembly->tables [MONO_TABLE_MODULE];
4868         alloc_table (table, 1);
4869         mono_image_fill_module_table (domain, moduleb, assembly);
4870
4871         /* Collect all types into a list sorted by their table_idx */
4872         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4873
4874         if (moduleb->types)
4875                 for (i = 0; i < moduleb->num_types; ++i) {
4876                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4877                         collect_types (&types, type);
4878                 }
4879
4880         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4881         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4882         table->rows += mono_ptr_array_size (types);
4883         alloc_table (table, table->rows);
4884
4885         /*
4886          * Emit type names + namespaces at one place inside the string heap,
4887          * so load_class_names () needs to touch fewer pages.
4888          */
4889         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4890                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4891                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4892         }
4893         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4894                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4895                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4896         }
4897
4898         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4899                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4900                 mono_image_get_type_info (domain, type, assembly);
4901         }
4902
4903         /* 
4904          * table->rows is already set above and in mono_image_fill_module_table.
4905          */
4906         /* add all the custom attributes at the end, once all the indexes are stable */
4907         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4908
4909         /* CAS assembly permissions */
4910         if (assemblyb->permissions_minimum)
4911                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4912         if (assemblyb->permissions_optional)
4913                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4914         if (assemblyb->permissions_refused)
4915                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4916
4917         module_add_cattrs (assembly, moduleb);
4918
4919         /* fixup tokens */
4920         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4921
4922         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4923          * the final tokens and don't need another fixup pass. */
4924
4925         if (moduleb->global_methods) {
4926                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4927                         MonoReflectionMethodBuilder *mb = mono_array_get (
4928                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4929                         mono_image_add_methodimpl (assembly, mb);
4930                 }
4931         }
4932
4933         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4934                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4935                 if (type->methods) {
4936                         for (j = 0; j < type->num_methods; ++j) {
4937                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4938                                         type->methods, MonoReflectionMethodBuilder*, j);
4939
4940                                 mono_image_add_methodimpl (assembly, mb);
4941                         }
4942                 }
4943         }
4944
4945         mono_ptr_array_destroy (types);
4946
4947         fixup_cattrs (assembly);
4948 }
4949
4950 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4951
4952 void
4953 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4954 {
4955         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4956 }
4957
4958 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4959
4960
4961 typedef struct {
4962         guint32 import_lookup_table;
4963         guint32 timestamp;
4964         guint32 forwarder;
4965         guint32 name_rva;
4966         guint32 import_address_table_rva;
4967 } MonoIDT;
4968
4969 typedef struct {
4970         guint32 name_rva;
4971         guint32 flags;
4972 } MonoILT;
4973
4974 #ifndef DISABLE_REFLECTION_EMIT
4975
4976 /*
4977  * mono_image_insert_string:
4978  * @module: module builder object
4979  * @str: a string
4980  *
4981  * Insert @str into the user string stream of @module.
4982  */
4983 guint32
4984 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4985 {
4986         MonoDynamicImage *assembly;
4987         guint32 idx;
4988         char buf [16];
4989         char *b = buf;
4990         
4991         if (!module->dynamic_image)
4992                 mono_image_module_basic_init (module);
4993
4994         assembly = module->dynamic_image;
4995         
4996         if (assembly->save) {
4997                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4998                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4999 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5000         {
5001                 char *swapped = g_malloc (2 * mono_string_length (str));
5002                 const char *p = (const char*)mono_string_chars (str);
5003
5004                 swap_with_size (swapped, p, 2, mono_string_length (str));
5005                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5006                 g_free (swapped);
5007         }
5008 #else
5009                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5010 #endif
5011                 mono_image_add_stream_data (&assembly->us, "", 1);
5012         } else {
5013                 idx = assembly->us.index ++;
5014         }
5015
5016         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5017
5018         return MONO_TOKEN_STRING | idx;
5019 }
5020
5021 guint32
5022 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5023 {
5024         MonoClass *klass;
5025         guint32 token = 0;
5026         MonoMethodSignature *sig;
5027
5028         klass = obj->vtable->klass;
5029         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5030                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5031                 MonoMethodSignature *old;
5032                 guint32 sig_token, parent;
5033                 int nargs, i;
5034
5035                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5036
5037                 nargs = mono_array_length (opt_param_types);
5038                 old = mono_method_signature (method);
5039                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5040
5041                 sig->hasthis = old->hasthis;
5042                 sig->explicit_this = old->explicit_this;
5043                 sig->call_convention = old->call_convention;
5044                 sig->generic_param_count = old->generic_param_count;
5045                 sig->param_count = old->param_count + nargs;
5046                 sig->sentinelpos = old->param_count;
5047                 sig->ret = old->ret;
5048
5049                 for (i = 0; i < old->param_count; i++)
5050                         sig->params [i] = old->params [i];
5051
5052                 for (i = 0; i < nargs; i++) {
5053                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5054                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5055                 }
5056
5057                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5058                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5059                 parent >>= MONO_TYPEDEFORREF_BITS;
5060
5061                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5062                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5063
5064                 sig_token = method_encode_signature (assembly, sig);
5065                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5066         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5067                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5068                 ReflectionMethodBuilder rmb;
5069                 guint32 parent, sig_token;
5070                 int nopt_args, nparams, ngparams, i;
5071                 char *name;
5072
5073                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5074                 rmb.opt_types = opt_param_types;
5075                 nopt_args = mono_array_length (opt_param_types);
5076
5077                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5078                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5079                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5080
5081                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5082                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5083                 sig->call_convention = rmb.call_conv;
5084                 sig->generic_param_count = ngparams;
5085                 sig->param_count = nparams + nopt_args;
5086                 sig->sentinelpos = nparams;
5087                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5088
5089                 for (i = 0; i < nparams; i++) {
5090                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5091                         sig->params [i] = mono_reflection_type_get_handle (rt);
5092                 }
5093
5094                 for (i = 0; i < nopt_args; i++) {
5095                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5096                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5097                 }
5098
5099                 sig_token = method_builder_encode_signature (assembly, &rmb);
5100
5101                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5102                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5103
5104                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5105                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5106
5107                 name = mono_string_to_utf8 (rmb.name);
5108                 token = mono_image_get_varargs_method_token (
5109                         assembly, parent, name, sig_token);
5110                 g_free (name);
5111         } else {
5112                 g_error ("requested method token for %s\n", klass->name);
5113         }
5114
5115         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5116         register_dyn_token (assembly, token, obj);
5117         return token;
5118 }
5119
5120 /*
5121  * mono_image_create_token:
5122  * @assembly: a dynamic assembly
5123  * @obj:
5124  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5125  *
5126  * Get a token to insert in the IL code stream for the given MemberInfo.
5127  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5128  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5129  * entry.
5130  */
5131 guint32
5132 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5133                                                  gboolean create_open_instance, gboolean register_token)
5134 {
5135         MonoClass *klass;
5136         guint32 token = 0;
5137
5138         klass = obj->vtable->klass;
5139
5140         /* Check for user defined reflection objects */
5141         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5142         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5143                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5144
5145         if (strcmp (klass->name, "MethodBuilder") == 0) {
5146                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5147                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5148
5149                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5150                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5151                 else
5152                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5153                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5154         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5155                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5156                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5157
5158                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5159                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5160                 else
5161                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5162                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5163         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5164                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5165                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5166                 if (tb->generic_params) {
5167                         token = mono_image_get_generic_field_token (assembly, fb);
5168                 } else {
5169                         if (tb->module->dynamic_image == assembly) {
5170                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5171                         } else {
5172                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5173                         }
5174                 }
5175         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5176                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5177                 if (create_open_instance && tb->generic_params) {
5178                         MonoType *type;
5179                         init_type_builder_generics (obj);
5180                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5181                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5182                         token = mono_metadata_token_from_dor (token);
5183                 } else if (tb->module->dynamic_image == assembly) {
5184                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5185                 } else {
5186                         MonoType *type;
5187                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5188                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5189                 }
5190         } else if (strcmp (klass->name, "MonoType") == 0) {
5191                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5192                 MonoClass *mc = mono_class_from_mono_type (type);
5193                 token = mono_metadata_token_from_dor (
5194                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5195         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5196                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5197                 token = mono_metadata_token_from_dor (
5198                         mono_image_typedef_or_ref (assembly, type));
5199         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5200                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5201                 token = mono_metadata_token_from_dor (
5202                         mono_image_typedef_or_ref (assembly, type));
5203         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5204                    strcmp (klass->name, "MonoMethod") == 0 ||
5205                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5206                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5207                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5208                 if (m->method->is_inflated) {
5209                         if (create_open_instance)
5210                                 token = mono_image_get_methodspec_token (assembly, m->method);
5211                         else
5212                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5213                 } else if ((m->method->klass->image == &assembly->image) &&
5214                          !m->method->klass->generic_class) {
5215                         static guint32 method_table_idx = 0xffffff;
5216                         if (m->method->klass->wastypebuilder) {
5217                                 /* we use the same token as the one that was assigned
5218                                  * to the Methodbuilder.
5219                                  * FIXME: do the equivalent for Fields.
5220                                  */
5221                                 token = m->method->token;
5222                         } else {
5223                                 /*
5224                                  * Each token should have a unique index, but the indexes are
5225                                  * assigned by managed code, so we don't know about them. An
5226                                  * easy solution is to count backwards...
5227                                  */
5228                                 method_table_idx --;
5229                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5230                         }
5231                 } else {
5232                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5233                 }
5234                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5235         } else if (strcmp (klass->name, "MonoField") == 0) {
5236                 MonoReflectionField *f = (MonoReflectionField *)obj;
5237                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5238                         static guint32 field_table_idx = 0xffffff;
5239                         field_table_idx --;
5240                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5241                 } else {
5242                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5243                 }
5244                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5245         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5246                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5247                 token = mono_image_get_array_token (assembly, m);
5248         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5249                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5250                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5251         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5252                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5253                 token = mono_metadata_token_from_dor (
5254                         mono_image_typedef_or_ref (assembly, type));
5255         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5256                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5257                 token = mono_image_get_field_on_inst_token (assembly, f);
5258         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5259                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5260                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5261         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5262                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5263                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5264         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5265                 MonoReflectionType *type = (MonoReflectionType *)obj;
5266                 token = mono_metadata_token_from_dor (
5267                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5268         } else {
5269                 g_error ("requested token for %s\n", klass->name);
5270         }
5271
5272         if (register_token)
5273                 mono_image_register_token (assembly, token, obj);
5274
5275         return token;
5276 }
5277
5278 /*
5279  * mono_image_register_token:
5280  *
5281  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5282  * the Module.ResolveXXXToken () methods to work.
5283  */
5284 void
5285 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5286 {
5287         MonoObject *prev;
5288
5289         dynamic_image_lock (assembly);
5290         prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5291         if (prev) {
5292                 /* There could be multiple MethodInfo objects with the same token */
5293                 //g_assert (prev == obj);
5294         } else {
5295                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5296         }
5297         dynamic_image_unlock (assembly);
5298 }
5299
5300 static MonoDynamicImage*
5301 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5302 {
5303         static const guchar entrycode [16] = {0xff, 0x25, 0};
5304         MonoDynamicImage *image;
5305         int i;
5306
5307         const char *version;
5308
5309         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5310                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5311         else
5312                 version = mono_get_runtime_info ()->runtime_version;
5313
5314 #if HAVE_BOEHM_GC
5315         /* The MonoGHashTable's need GC tracking */
5316         image = GC_MALLOC (sizeof (MonoDynamicImage));
5317 #else
5318         image = g_new0 (MonoDynamicImage, 1);
5319 #endif
5320
5321         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5322         
5323         /*g_print ("created image %p\n", image);*/
5324         /* keep in sync with image.c */
5325         image->image.name = assembly_name;
5326         image->image.assembly_name = image->image.name; /* they may be different */
5327         image->image.module_name = module_name;
5328         image->image.version = g_strdup (version);
5329         image->image.md_version_major = 1;
5330         image->image.md_version_minor = 1;
5331         image->image.dynamic = TRUE;
5332
5333         image->image.references = g_new0 (MonoAssembly*, 1);
5334         image->image.references [0] = NULL;
5335
5336         mono_image_init (&image->image);
5337
5338         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");
5339         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5340         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5341         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5342         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5343         image->handleref = g_hash_table_new (NULL, NULL);
5344         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");
5345         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5346         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");
5347         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");
5348         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5349         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5350         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5351         image->gen_params = g_ptr_array_new ();
5352         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5353
5354         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5355         string_heap_init (&image->sheap);
5356         mono_image_add_stream_data (&image->us, "", 1);
5357         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5358         /* import tables... */
5359         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5360         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5361         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5362         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5363         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5364         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5365         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5366         stream_data_align (&image->code);
5367
5368         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5369
5370         for (i=0; i < MONO_TABLE_NUM; ++i) {
5371                 image->tables [i].next_idx = 1;
5372                 image->tables [i].columns = table_sizes [i];
5373         }
5374
5375         image->image.assembly = (MonoAssembly*)assembly;
5376         image->run = assembly->run;
5377         image->save = assembly->save;
5378         image->pe_kind = 0x1; /* ILOnly */
5379         image->machine = 0x14c; /* I386 */
5380         
5381         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5382
5383         dynamic_images_lock ();
5384
5385         if (!dynamic_images)
5386                 dynamic_images = g_ptr_array_new ();
5387
5388         g_ptr_array_add (dynamic_images, image);
5389
5390         dynamic_images_unlock ();
5391
5392         return image;
5393 }
5394 #endif
5395
5396 static void
5397 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5398 {
5399         g_free (key);
5400 }
5401
5402 static void
5403 release_hashtable (MonoGHashTable **hash)
5404 {
5405         if (*hash) {
5406                 mono_g_hash_table_destroy (*hash);
5407                 *hash = NULL;
5408         }
5409 }
5410
5411 void
5412 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5413 {
5414         release_hashtable (&image->token_fixups);
5415         release_hashtable (&image->handleref_managed);
5416         release_hashtable (&image->tokens);
5417         release_hashtable (&image->remapped_tokens);
5418         release_hashtable (&image->generic_def_objects);
5419         release_hashtable (&image->methodspec);
5420 }
5421
5422 // Free dynamic image pass one: Free resources but not image itself
5423 void
5424 mono_dynamic_image_free (MonoDynamicImage *image)
5425 {
5426         MonoDynamicImage *di = image;
5427         GList *list;
5428         int i;
5429
5430         if (di->methodspec)
5431                 mono_g_hash_table_destroy (di->methodspec);
5432         if (di->typespec)
5433                 g_hash_table_destroy (di->typespec);
5434         if (di->typeref)
5435                 g_hash_table_destroy (di->typeref);
5436         if (di->handleref)
5437                 g_hash_table_destroy (di->handleref);
5438         if (di->handleref_managed)
5439                 mono_g_hash_table_destroy (di->handleref_managed);
5440         if (di->tokens)
5441                 mono_g_hash_table_destroy (di->tokens);
5442         if (di->remapped_tokens)
5443                 mono_g_hash_table_destroy (di->remapped_tokens);
5444         if (di->generic_def_objects)
5445                 mono_g_hash_table_destroy (di->generic_def_objects);
5446         if (di->blob_cache) {
5447                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5448                 g_hash_table_destroy (di->blob_cache);
5449         }
5450         if (di->standalonesig_cache)
5451                 g_hash_table_destroy (di->standalonesig_cache);
5452         for (list = di->array_methods; list; list = list->next) {
5453                 ArrayMethod *am = (ArrayMethod *)list->data;
5454                 g_free (am->sig);
5455                 g_free (am->name);
5456                 g_free (am);
5457         }
5458         g_list_free (di->array_methods);
5459         if (di->gen_params) {
5460                 for (i = 0; i < di->gen_params->len; i++) {
5461                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5462                         mono_gc_deregister_root ((char*) &entry->gparam);
5463                         g_free (entry);
5464                 }
5465                 g_ptr_array_free (di->gen_params, TRUE);
5466         }
5467         if (di->token_fixups)
5468                 mono_g_hash_table_destroy (di->token_fixups);
5469         if (di->method_to_table_idx)
5470                 g_hash_table_destroy (di->method_to_table_idx);
5471         if (di->field_to_table_idx)
5472                 g_hash_table_destroy (di->field_to_table_idx);
5473         if (di->method_aux_hash)
5474                 g_hash_table_destroy (di->method_aux_hash);
5475         if (di->vararg_aux_hash)
5476                 g_hash_table_destroy (di->vararg_aux_hash);
5477         g_free (di->strong_name);
5478         g_free (di->win32_res);
5479         if (di->public_key)
5480                 g_free (di->public_key);
5481
5482         /*g_print ("string heap destroy for image %p\n", di);*/
5483         mono_dynamic_stream_reset (&di->sheap);
5484         mono_dynamic_stream_reset (&di->code);
5485         mono_dynamic_stream_reset (&di->resources);
5486         mono_dynamic_stream_reset (&di->us);
5487         mono_dynamic_stream_reset (&di->blob);
5488         mono_dynamic_stream_reset (&di->tstream);
5489         mono_dynamic_stream_reset (&di->guid);
5490         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5491                 g_free (di->tables [i].values);
5492         }
5493
5494         dynamic_images_lock ();
5495
5496         if (dynamic_images)
5497                 g_ptr_array_remove (dynamic_images, di);
5498
5499         dynamic_images_unlock ();
5500 }
5501
5502 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5503 void
5504 mono_dynamic_image_free_image (MonoDynamicImage *image)
5505 {
5506         /* See create_dynamic_mono_image () */
5507 #if HAVE_BOEHM_GC
5508         /* Allocated using GC_MALLOC */
5509 #else
5510         g_free (image);
5511 #endif
5512 }
5513
5514 #ifndef DISABLE_REFLECTION_EMIT
5515
5516 /*
5517  * mono_image_basic_init:
5518  * @assembly: an assembly builder object
5519  *
5520  * Create the MonoImage that represents the assembly builder and setup some
5521  * of the helper hash table and the basic metadata streams.
5522  */
5523 void
5524 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5525 {
5526         MonoDynamicAssembly *assembly;
5527         MonoDynamicImage *image;
5528         MonoDomain *domain = mono_object_domain (assemblyb);
5529         
5530         if (assemblyb->dynamic_assembly)
5531                 return;
5532
5533 #if HAVE_BOEHM_GC
5534         /* assembly->assembly.image might be GC allocated */
5535         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5536 #else
5537         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5538 #endif
5539
5540         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5541         
5542         assembly->assembly.ref_count = 1;
5543         assembly->assembly.dynamic = TRUE;
5544         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5545         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5546         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5547         if (assemblyb->culture)
5548                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5549         else
5550                 assembly->assembly.aname.culture = g_strdup ("");
5551
5552         if (assemblyb->version) {
5553                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5554                         char **version = g_strsplit (vstr, ".", 4);
5555                         char **parts = version;
5556                         assembly->assembly.aname.major = atoi (*parts++);
5557                         assembly->assembly.aname.minor = atoi (*parts++);
5558                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5559                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5560
5561                         g_strfreev (version);
5562                         g_free (vstr);
5563         } else {
5564                         assembly->assembly.aname.major = 0;
5565                         assembly->assembly.aname.minor = 0;
5566                         assembly->assembly.aname.build = 0;
5567                         assembly->assembly.aname.revision = 0;
5568         }
5569
5570         assembly->run = assemblyb->access != 2;
5571         assembly->save = assemblyb->access != 1;
5572         assembly->domain = domain;
5573
5574         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5575         image->initial_image = TRUE;
5576         assembly->assembly.aname.name = image->image.name;
5577         assembly->assembly.image = &image->image;
5578         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5579                 /* -1 to correct for the trailing NULL byte */
5580                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5581                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5582                 }
5583                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5584         }
5585
5586         mono_domain_assemblies_lock (domain);
5587         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5588         mono_domain_assemblies_unlock (domain);
5589
5590         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5591         
5592         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5593         
5594         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5595 }
5596
5597 #endif /* !DISABLE_REFLECTION_EMIT */
5598
5599 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5600
5601 static int
5602 calc_section_size (MonoDynamicImage *assembly)
5603 {
5604         int nsections = 0;
5605
5606         /* alignment constraints */
5607         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5608         g_assert ((assembly->code.index % 4) == 0);
5609         assembly->meta_size += 3;
5610         assembly->meta_size &= ~3;
5611         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5612         g_assert ((assembly->resources.index % 4) == 0);
5613
5614         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5615         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5616         nsections++;
5617
5618         if (assembly->win32_res) {
5619                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5620
5621                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5622                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5623                 nsections++;
5624         }
5625
5626         assembly->sections [MONO_SECTION_RELOC].size = 12;
5627         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5628         nsections++;
5629
5630         return nsections;
5631 }
5632
5633 typedef struct {
5634         guint32 id;
5635         guint32 offset;
5636         GSList *children;
5637         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5638 } ResTreeNode;
5639
5640 static int
5641 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5642 {
5643         ResTreeNode *t1 = (ResTreeNode*)a;
5644         ResTreeNode *t2 = (ResTreeNode*)b;
5645
5646         return t1->id - t2->id;
5647 }
5648
5649 /*
5650  * resource_tree_create:
5651  *
5652  *  Organize the resources into a resource tree.
5653  */
5654 static ResTreeNode *
5655 resource_tree_create (MonoArray *win32_resources)
5656 {
5657         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5658         GSList *l;
5659         int i;
5660
5661         tree = g_new0 (ResTreeNode, 1);
5662         
5663         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5664                 MonoReflectionWin32Resource *win32_res =
5665                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5666
5667                 /* Create node */
5668
5669                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5670                 lang_node = g_new0 (ResTreeNode, 1);
5671                 lang_node->id = win32_res->lang_id;
5672                 lang_node->win32_res = win32_res;
5673
5674                 /* Create type node if neccesary */
5675                 type_node = NULL;
5676                 for (l = tree->children; l; l = l->next)
5677                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5678                                 type_node = (ResTreeNode*)l->data;
5679                                 break;
5680                         }
5681
5682                 if (!type_node) {
5683                         type_node = g_new0 (ResTreeNode, 1);
5684                         type_node->id = win32_res->res_type;
5685
5686                         /* 
5687                          * The resource types have to be sorted otherwise
5688                          * Windows Explorer can't display the version information.
5689                          */
5690                         tree->children = g_slist_insert_sorted (tree->children, 
5691                                 type_node, resource_tree_compare_by_id);
5692                 }
5693
5694                 /* Create res node if neccesary */
5695                 res_node = NULL;
5696                 for (l = type_node->children; l; l = l->next)
5697                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5698                                 res_node = (ResTreeNode*)l->data;
5699                                 break;
5700                         }
5701
5702                 if (!res_node) {
5703                         res_node = g_new0 (ResTreeNode, 1);
5704                         res_node->id = win32_res->res_id;
5705                         type_node->children = g_slist_append (type_node->children, res_node);
5706                 }
5707
5708                 res_node->children = g_slist_append (res_node->children, lang_node);
5709         }
5710
5711         return tree;
5712 }
5713
5714 /*
5715  * resource_tree_encode:
5716  * 
5717  *   Encode the resource tree into the format used in the PE file.
5718  */
5719 static void
5720 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5721 {
5722         char *entries;
5723         MonoPEResourceDir dir;
5724         MonoPEResourceDirEntry dir_entry;
5725         MonoPEResourceDataEntry data_entry;
5726         GSList *l;
5727         guint32 res_id_entries;
5728
5729         /*
5730          * For the format of the resource directory, see the article
5731          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5732          * Matt Pietrek
5733          */
5734
5735         memset (&dir, 0, sizeof (dir));
5736         memset (&dir_entry, 0, sizeof (dir_entry));
5737         memset (&data_entry, 0, sizeof (data_entry));
5738
5739         g_assert (sizeof (dir) == 16);
5740         g_assert (sizeof (dir_entry) == 8);
5741         g_assert (sizeof (data_entry) == 16);
5742
5743         node->offset = p - begin;
5744
5745         /* IMAGE_RESOURCE_DIRECTORY */
5746         res_id_entries = g_slist_length (node->children);
5747         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5748
5749         memcpy (p, &dir, sizeof (dir));
5750         p += sizeof (dir);
5751
5752         /* Reserve space for entries */
5753         entries = p;
5754         p += sizeof (dir_entry) * res_id_entries;
5755
5756         /* Write children */
5757         for (l = node->children; l; l = l->next) {
5758                 ResTreeNode *child = (ResTreeNode*)l->data;
5759
5760                 if (child->win32_res) {
5761                         guint32 size;
5762
5763                         child->offset = p - begin;
5764
5765                         /* IMAGE_RESOURCE_DATA_ENTRY */
5766                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5767                         size = mono_array_length (child->win32_res->res_data);
5768                         data_entry.rde_size = GUINT32_TO_LE (size);
5769
5770                         memcpy (p, &data_entry, sizeof (data_entry));
5771                         p += sizeof (data_entry);
5772
5773                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5774                         p += size;
5775                 } else {
5776                         resource_tree_encode (child, begin, p, &p);
5777                 }
5778         }
5779
5780         /* IMAGE_RESOURCE_ENTRY */
5781         for (l = node->children; l; l = l->next) {
5782                 ResTreeNode *child = (ResTreeNode*)l->data;
5783
5784                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5785                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5786
5787                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5788                 entries += sizeof (dir_entry);
5789         }
5790
5791         *endbuf = p;
5792 }
5793
5794 static void
5795 resource_tree_free (ResTreeNode * node)
5796 {
5797         GSList * list;
5798         for (list = node->children; list; list = list->next)
5799                 resource_tree_free ((ResTreeNode*)list->data);
5800         g_slist_free(node->children);
5801         g_free (node);
5802 }
5803
5804 static void
5805 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5806 {
5807         char *buf;
5808         char *p;
5809         guint32 size, i;
5810         MonoReflectionWin32Resource *win32_res;
5811         ResTreeNode *tree;
5812
5813         if (!assemblyb->win32_resources)
5814                 return;
5815
5816         /*
5817          * Resources are stored in a three level tree inside the PE file.
5818          * - level one contains a node for each type of resource
5819          * - level two contains a node for each resource
5820          * - level three contains a node for each instance of a resource for a
5821          *   specific language.
5822          */
5823
5824         tree = resource_tree_create (assemblyb->win32_resources);
5825
5826         /* Estimate the size of the encoded tree */
5827         size = 0;
5828         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5829                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5830                 size += mono_array_length (win32_res->res_data);
5831         }
5832         /* Directory structure */
5833         size += mono_array_length (assemblyb->win32_resources) * 256;
5834         p = buf = g_malloc (size);
5835
5836         resource_tree_encode (tree, p, p, &p);
5837
5838         g_assert (p - buf <= size);
5839
5840         assembly->win32_res = g_malloc (p - buf);
5841         assembly->win32_res_size = p - buf;
5842         memcpy (assembly->win32_res, buf, p - buf);
5843
5844         g_free (buf);
5845         resource_tree_free (tree);
5846 }
5847
5848 static void
5849 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5850 {
5851         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5852         int i;
5853
5854         p += sizeof (MonoPEResourceDir);
5855         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5856                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5857                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5858                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5859                         fixup_resource_directory (res_section, child, rva);
5860                 } else {
5861                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5862                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5863                 }
5864
5865                 p += sizeof (MonoPEResourceDirEntry);
5866         }
5867 }
5868
5869 static void
5870 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5871 {
5872         guint32 dummy;
5873         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5874                 g_error ("WriteFile returned %d\n", GetLastError ());
5875 }
5876
5877 /*
5878  * mono_image_create_pefile:
5879  * @mb: a module builder object
5880  * 
5881  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5882  * assembly->pefile where it can be easily retrieved later in chunks.
5883  */
5884 void
5885 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5886 {
5887         MonoMSDOSHeader *msdos;
5888         MonoDotNetHeader *header;
5889         MonoSectionTable *section;
5890         MonoCLIHeader *cli_header;
5891         guint32 size, image_size, virtual_base, text_offset;
5892         guint32 header_start, section_start, file_offset, virtual_offset;
5893         MonoDynamicImage *assembly;
5894         MonoReflectionAssemblyBuilder *assemblyb;
5895         MonoDynamicStream pefile_stream = {0};
5896         MonoDynamicStream *pefile = &pefile_stream;
5897         int i, nsections;
5898         guint32 *rva, value;
5899         guchar *p;
5900         static const unsigned char msheader[] = {
5901                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5902                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5903                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5904                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5905                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5906                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5907                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5908                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5909         };
5910
5911         assemblyb = mb->assemblyb;
5912
5913         mono_image_basic_init (assemblyb);
5914         assembly = mb->dynamic_image;
5915
5916         assembly->pe_kind = assemblyb->pe_kind;
5917         assembly->machine = assemblyb->machine;
5918         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5919         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5920         
5921         mono_image_build_metadata (mb);
5922
5923         if (mb->is_main && assemblyb->resources) {
5924                 int len = mono_array_length (assemblyb->resources);
5925                 for (i = 0; i < len; ++i)
5926                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5927         }
5928
5929         if (mb->resources) {
5930                 int len = mono_array_length (mb->resources);
5931                 for (i = 0; i < len; ++i)
5932                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5933         }
5934
5935         build_compressed_metadata (assembly);
5936
5937         if (mb->is_main)
5938                 assembly_add_win32_resources (assembly, assemblyb);
5939
5940         nsections = calc_section_size (assembly);
5941         
5942         /* The DOS header and stub */
5943         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5944         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5945
5946         /* the dotnet header */
5947         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5948
5949         /* the section tables */
5950         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5951
5952         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5953         virtual_offset = VIRT_ALIGN;
5954         image_size = 0;
5955
5956         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5957                 if (!assembly->sections [i].size)
5958                         continue;
5959                 /* align offsets */
5960                 file_offset += FILE_ALIGN - 1;
5961                 file_offset &= ~(FILE_ALIGN - 1);
5962                 virtual_offset += VIRT_ALIGN - 1;
5963                 virtual_offset &= ~(VIRT_ALIGN - 1);
5964
5965                 assembly->sections [i].offset = file_offset;
5966                 assembly->sections [i].rva = virtual_offset;
5967
5968                 file_offset += assembly->sections [i].size;
5969                 virtual_offset += assembly->sections [i].size;
5970                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5971         }
5972
5973         file_offset += FILE_ALIGN - 1;
5974         file_offset &= ~(FILE_ALIGN - 1);
5975
5976         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5977
5978         /* back-patch info */
5979         msdos = (MonoMSDOSHeader*)pefile->data;
5980         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5981
5982         header = (MonoDotNetHeader*)(pefile->data + header_start);
5983         header->pesig [0] = 'P';
5984         header->pesig [1] = 'E';
5985         
5986         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5987         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5988         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5989         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5990         if (assemblyb->pekind == 1) {
5991                 /* it's a dll */
5992                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5993         } else {
5994                 /* it's an exe */
5995                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5996         }
5997
5998         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5999
6000         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6001         header->pe.pe_major = 6;
6002         header->pe.pe_minor = 0;
6003         size = assembly->sections [MONO_SECTION_TEXT].size;
6004         size += FILE_ALIGN - 1;
6005         size &= ~(FILE_ALIGN - 1);
6006         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6007         size = assembly->sections [MONO_SECTION_RSRC].size;
6008         size += FILE_ALIGN - 1;
6009         size &= ~(FILE_ALIGN - 1);
6010         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6011         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6012         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6013         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6014         /* pe_rva_entry_point always at the beginning of the text section */
6015         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6016
6017         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6018         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6019         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6020         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6021         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6022         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6023         size = section_start;
6024         size += FILE_ALIGN - 1;
6025         size &= ~(FILE_ALIGN - 1);
6026         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6027         size = image_size;
6028         size += VIRT_ALIGN - 1;
6029         size &= ~(VIRT_ALIGN - 1);
6030         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6031
6032         /*
6033         // Translate the PEFileKind value to the value expected by the Windows loader
6034         */
6035         {
6036                 short kind;
6037
6038                 /*
6039                 // PEFileKinds.Dll == 1
6040                 // PEFileKinds.ConsoleApplication == 2
6041                 // PEFileKinds.WindowApplication == 3
6042                 //
6043                 // need to get:
6044                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6045                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6046                 */
6047                 if (assemblyb->pekind == 3)
6048                         kind = 2;
6049                 else
6050                         kind = 3;
6051                 
6052                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6053         }    
6054         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6055         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6056         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6057         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6058         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6059         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6060
6061         /* fill data directory entries */
6062
6063         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6064         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6065
6066         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6067         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6068
6069         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6070         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6071         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6072         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6073         /* patch entrypoint name */
6074         if (assemblyb->pekind == 1)
6075                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6076         else
6077                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6078         /* patch imported function RVA name */
6079         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6080         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6081
6082         /* the import table */
6083         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6084         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6085         /* patch imported dll RVA name and other entries in the dir */
6086         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6087         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6088         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6089         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6090         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6091         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6092
6093         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6094         value = (assembly->text_rva + assembly->imp_names_offset);
6095         *p++ = (value) & 0xff;
6096         *p++ = (value >> 8) & (0xff);
6097         *p++ = (value >> 16) & (0xff);
6098         *p++ = (value >> 24) & (0xff);
6099
6100         /* the CLI header info */
6101         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6102         cli_header->ch_size = GUINT32_FROM_LE (72);
6103         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6104         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6105         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6106         if (assemblyb->entry_point) {
6107                 guint32 table_idx = 0;
6108                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6109                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6110                         table_idx = methodb->table_idx;
6111                 } else {
6112                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6113                 }
6114                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6115         } else {
6116                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6117         }
6118         /* The embedded managed resources */
6119         text_offset = assembly->text_rva + assembly->code.index;
6120         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6121         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6122         text_offset += assembly->resources.index;
6123         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6124         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6125         text_offset += assembly->meta_size;
6126         if (assembly->strong_name_size) {
6127                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6128                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6129                 text_offset += assembly->strong_name_size;
6130         }
6131
6132         /* write the section tables and section content */
6133         section = (MonoSectionTable*)(pefile->data + section_start);
6134         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6135                 static const char section_names [][7] = {
6136                         ".text", ".rsrc", ".reloc"
6137                 };
6138                 if (!assembly->sections [i].size)
6139                         continue;
6140                 strcpy (section->st_name, section_names [i]);
6141                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6142                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6143                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6144                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6145                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6146                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6147                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6148                 section ++;
6149         }
6150         
6151         checked_write_file (file, pefile->data, pefile->index);
6152         
6153         mono_dynamic_stream_reset (pefile);
6154         
6155         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6156                 if (!assembly->sections [i].size)
6157                         continue;
6158                 
6159                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6160                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6161                 
6162                 switch (i) {
6163                 case MONO_SECTION_TEXT:
6164                         /* patch entry point */
6165                         p = (guchar*)(assembly->code.data + 2);
6166                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6167                         *p++ = (value) & 0xff;
6168                         *p++ = (value >> 8) & 0xff;
6169                         *p++ = (value >> 16) & 0xff;
6170                         *p++ = (value >> 24) & 0xff;
6171                 
6172                         checked_write_file (file, assembly->code.data, assembly->code.index);
6173                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6174                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6175                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6176                                 
6177
6178                         g_free (assembly->image.raw_metadata);
6179                         break;
6180                 case MONO_SECTION_RELOC: {
6181                         struct {
6182                                 guint32 page_rva;
6183                                 guint32 block_size;
6184                                 guint16 type_and_offset;
6185                                 guint16 term;
6186                         } reloc;
6187                         
6188                         g_assert (sizeof (reloc) == 12);
6189                         
6190                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6191                         reloc.block_size = GUINT32_FROM_LE (12);
6192                         
6193                         /* 
6194                          * the entrypoint is always at the start of the text section 
6195                          * 3 is IMAGE_REL_BASED_HIGHLOW
6196                          * 2 is patch_size_rva - text_rva
6197                          */
6198                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6199                         reloc.term = 0;
6200                         
6201                         checked_write_file (file, &reloc, sizeof (reloc));
6202                         
6203                         break;
6204                 }
6205                 case MONO_SECTION_RSRC:
6206                         if (assembly->win32_res) {
6207
6208                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6209                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6210                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6211                         }
6212                         break;
6213                 default:
6214                         g_assert_not_reached ();
6215                 }
6216         }
6217         
6218         /* check that the file is properly padded */
6219         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6220                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6221         if (! SetEndOfFile (file))
6222                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6223         
6224         mono_dynamic_stream_reset (&assembly->code);
6225         mono_dynamic_stream_reset (&assembly->us);
6226         mono_dynamic_stream_reset (&assembly->blob);
6227         mono_dynamic_stream_reset (&assembly->guid);
6228         mono_dynamic_stream_reset (&assembly->sheap);
6229
6230         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6231         g_hash_table_destroy (assembly->blob_cache);
6232         assembly->blob_cache = NULL;
6233 }
6234
6235 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6236
6237 void
6238 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6239 {
6240         g_assert_not_reached ();
6241 }
6242
6243 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6244
6245 #ifndef DISABLE_REFLECTION_EMIT
6246
6247 MonoReflectionModule *
6248 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6249 {
6250         char *name;
6251         MonoImage *image;
6252         MonoImageOpenStatus status;
6253         MonoDynamicAssembly *assembly;
6254         guint32 module_count;
6255         MonoImage **new_modules;
6256         gboolean *new_modules_loaded;
6257         
6258         name = mono_string_to_utf8 (fileName);
6259
6260         image = mono_image_open (name, &status);
6261         if (!image) {
6262                 MonoException *exc;
6263                 if (status == MONO_IMAGE_ERROR_ERRNO)
6264                         exc = mono_get_exception_file_not_found (fileName);
6265                 else
6266                         exc = mono_get_exception_bad_image_format (name);
6267                 g_free (name);
6268                 mono_raise_exception (exc);
6269         }
6270
6271         g_free (name);
6272
6273         assembly = ab->dynamic_assembly;
6274         image->assembly = (MonoAssembly*)assembly;
6275
6276         module_count = image->assembly->image->module_count;
6277         new_modules = g_new0 (MonoImage *, module_count + 1);
6278         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6279
6280         if (image->assembly->image->modules)
6281                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6282         if (image->assembly->image->modules_loaded)
6283                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6284         new_modules [module_count] = image;
6285         new_modules_loaded [module_count] = TRUE;
6286         mono_image_addref (image);
6287
6288         g_free (image->assembly->image->modules);
6289         image->assembly->image->modules = new_modules;
6290         image->assembly->image->modules_loaded = new_modules_loaded;
6291         image->assembly->image->module_count ++;
6292
6293         mono_assembly_load_references (image, &status);
6294         if (status) {
6295                 mono_image_close (image);
6296                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6297         }
6298
6299         return mono_module_get_object (mono_domain_get (), image);
6300 }
6301
6302 #endif /* DISABLE_REFLECTION_EMIT */
6303
6304 /*
6305  * We need to return always the same object for MethodInfo, FieldInfo etc..
6306  * but we need to consider the reflected type.
6307  * type uses a different hash, since it uses custom hash/equal functions.
6308  */
6309
6310 typedef struct {
6311         gpointer item;
6312         MonoClass *refclass;
6313 } ReflectedEntry;
6314
6315 static gboolean
6316 reflected_equal (gconstpointer a, gconstpointer b) {
6317         const ReflectedEntry *ea = a;
6318         const ReflectedEntry *eb = b;
6319
6320         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6321 }
6322
6323 static guint
6324 reflected_hash (gconstpointer a) {
6325         const ReflectedEntry *ea = a;
6326         return mono_aligned_addr_hash (ea->item);
6327 }
6328
6329 #define CHECK_OBJECT(t,p,k)     \
6330         do {    \
6331                 t _obj; \
6332                 ReflectedEntry e;       \
6333                 e.item = (p);   \
6334                 e.refclass = (k);       \
6335                 mono_domain_lock (domain);      \
6336                 if (!domain->refobject_hash)    \
6337                         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");  \
6338                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6339                         mono_domain_unlock (domain);    \
6340                         return _obj;    \
6341                 }       \
6342         mono_domain_unlock (domain); \
6343         } while (0)
6344
6345 #ifdef HAVE_BOEHM_GC
6346 /* ReflectedEntry doesn't need to be GC tracked */
6347 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6348 #define FREE_REFENTRY(entry) g_free ((entry))
6349 #define REFENTRY_REQUIRES_CLEANUP
6350 #else
6351 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6352 /* FIXME: */
6353 #define FREE_REFENTRY(entry)
6354 #endif
6355
6356 #define CACHE_OBJECT(t,p,o,k)   \
6357         do {    \
6358                 t _obj; \
6359         ReflectedEntry pe; \
6360         pe.item = (p); \
6361         pe.refclass = (k); \
6362         mono_domain_lock (domain); \
6363                 if (!domain->refobject_hash)    \
6364                         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");  \
6365         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6366         if (!_obj) { \
6367                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6368                     e->item = (p);      \
6369                     e->refclass = (k);  \
6370                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6371             _obj = o; \
6372         } \
6373                 mono_domain_unlock (domain);    \
6374         return _obj; \
6375         } while (0)
6376
6377 static void
6378 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6379 {
6380         mono_domain_lock (domain);
6381         if (domain->refobject_hash) {
6382         ReflectedEntry pe;
6383                 gpointer orig_pe, orig_value;
6384
6385                 pe.item = o;
6386                 pe.refclass = klass;
6387                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6388                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6389                         FREE_REFENTRY (orig_pe);
6390                 }
6391         }
6392         mono_domain_unlock (domain);
6393 }
6394
6395 #ifdef REFENTRY_REQUIRES_CLEANUP
6396 static void
6397 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6398 {
6399         FREE_REFENTRY (key);
6400 }
6401 #endif
6402
6403 void
6404 mono_reflection_cleanup_domain (MonoDomain *domain)
6405 {
6406         if (domain->refobject_hash) {
6407 /*let's avoid scanning the whole hashtable if not needed*/
6408 #ifdef REFENTRY_REQUIRES_CLEANUP
6409                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6410 #endif
6411                 mono_g_hash_table_destroy (domain->refobject_hash);
6412                 domain->refobject_hash = NULL;
6413         }
6414 }
6415
6416 #ifndef DISABLE_REFLECTION_EMIT
6417 static gpointer
6418 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6419 {
6420         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6421 }
6422
6423 static gpointer
6424 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6425 {
6426         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6427 }
6428
6429 void
6430 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6431 {
6432         MonoDynamicImage *image = moduleb->dynamic_image;
6433         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6434         if (!image) {
6435                 MonoError error;
6436                 int module_count;
6437                 MonoImage **new_modules;
6438                 MonoImage *ass;
6439                 char *name, *fqname;
6440                 /*
6441                  * FIXME: we already created an image in mono_image_basic_init (), but
6442                  * we don't know which module it belongs to, since that is only 
6443                  * determined at assembly save time.
6444                  */
6445                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6446                 name = mono_string_to_utf8 (ab->name);
6447                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6448                 if (!mono_error_ok (&error)) {
6449                         g_free (name);
6450                         mono_error_raise_exception (&error);
6451                 }
6452                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6453
6454                 moduleb->module.image = &image->image;
6455                 moduleb->dynamic_image = image;
6456                 register_module (mono_object_domain (moduleb), moduleb, image);
6457
6458                 /* register the module with the assembly */
6459                 ass = ab->dynamic_assembly->assembly.image;
6460                 module_count = ass->module_count;
6461                 new_modules = g_new0 (MonoImage *, module_count + 1);
6462
6463                 if (ass->modules)
6464                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6465                 new_modules [module_count] = &image->image;
6466                 mono_image_addref (&image->image);
6467
6468                 g_free (ass->modules);
6469                 ass->modules = new_modules;
6470                 ass->module_count ++;
6471         }
6472 }
6473
6474 void
6475 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6476 {
6477         MonoDynamicImage *image = moduleb->dynamic_image;
6478
6479         g_assert (type->type);
6480         image->wrappers_type = mono_class_from_mono_type (type->type);
6481 }
6482
6483 #endif
6484
6485 /*
6486  * mono_assembly_get_object:
6487  * @domain: an app domain
6488  * @assembly: an assembly
6489  *
6490  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6491  */
6492 MonoReflectionAssembly*
6493 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6494 {
6495         static MonoClass *assembly_type;
6496         MonoReflectionAssembly *res;
6497         
6498         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6499         if (!assembly_type) {
6500                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6501                 if (klass == NULL)
6502                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6503                 g_assert (klass);
6504                 assembly_type = klass;
6505         }
6506         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6507         res->assembly = assembly;
6508
6509         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6510 }
6511
6512
6513
6514 MonoReflectionModule*   
6515 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6516 {
6517         static MonoClass *module_type;
6518         MonoReflectionModule *res;
6519         char* basename;
6520         
6521         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6522         if (!module_type) {
6523                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6524                 if (klass == NULL)
6525                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6526                 g_assert (klass);
6527                 module_type = klass;
6528         }
6529         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6530
6531         res->image = image;
6532         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6533
6534         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6535         basename = g_path_get_basename (image->name);
6536         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6537         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6538         
6539         g_free (basename);
6540
6541         if (image->assembly->image == image) {
6542                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6543         } else {
6544                 int i;
6545                 res->token = 0;
6546                 if (image->assembly->image->modules) {
6547                         for (i = 0; i < image->assembly->image->module_count; i++) {
6548                                 if (image->assembly->image->modules [i] == image)
6549                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6550                         }
6551                         g_assert (res->token);
6552                 }
6553         }
6554
6555         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6556 }
6557
6558 MonoReflectionModule*   
6559 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6560 {
6561         static MonoClass *module_type;
6562         MonoReflectionModule *res;
6563         MonoTableInfo *table;
6564         guint32 cols [MONO_FILE_SIZE];
6565         const char *name;
6566         guint32 i, name_idx;
6567         const char *val;
6568         
6569         if (!module_type) {
6570                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6571                 if (klass == NULL)
6572                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6573                 g_assert (klass);
6574                 module_type = klass;
6575         }
6576         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6577
6578         table = &image->tables [MONO_TABLE_FILE];
6579         g_assert (table_index < table->rows);
6580         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6581
6582         res->image = NULL;
6583         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6584         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6585
6586         /* Check whenever the row has a corresponding row in the moduleref table */
6587         table = &image->tables [MONO_TABLE_MODULEREF];
6588         for (i = 0; i < table->rows; ++i) {
6589                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6590                 val = mono_metadata_string_heap (image, name_idx);
6591                 if (strcmp (val, name) == 0)
6592                         res->image = image->modules [i];
6593         }
6594
6595         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6596         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6597         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6598         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6599         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6600
6601         return res;
6602 }
6603
6604 static gboolean
6605 verify_safe_for_managed_space (MonoType *type)
6606 {
6607         switch (type->type) {
6608 #ifdef DEBUG_HARDER
6609         case MONO_TYPE_ARRAY:
6610                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6611         case MONO_TYPE_PTR:
6612                 return verify_safe_for_managed_space (type->data.type);
6613         case MONO_TYPE_SZARRAY:
6614                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6615         case MONO_TYPE_GENERICINST: {
6616                 MonoGenericInst *inst = type->data.generic_class->inst;
6617                 int i;
6618                 if (!inst->is_open)
6619                         break;
6620                 for (i = 0; i < inst->type_argc; ++i)
6621                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6622                                 return FALSE;
6623                 return TRUE;
6624         }
6625 #endif
6626         case MONO_TYPE_VAR:
6627         case MONO_TYPE_MVAR:
6628                 return TRUE;
6629         default:
6630                 return TRUE;
6631         }
6632 }
6633
6634 static MonoType*
6635 mono_type_normalize (MonoType *type)
6636 {
6637         int i;
6638         MonoGenericClass *gclass;
6639         MonoGenericInst *ginst;
6640         MonoClass *gtd;
6641         MonoGenericContainer *gcontainer;
6642         MonoType **argv = NULL;
6643         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6644
6645         if (type->type != MONO_TYPE_GENERICINST)
6646                 return type;
6647
6648         gclass = type->data.generic_class;
6649         ginst = gclass->context.class_inst;
6650         if (!ginst->is_open)
6651                 return type;
6652
6653         gtd = gclass->container_class;
6654         gcontainer = gtd->generic_container;
6655         argv = g_newa (MonoType*, ginst->type_argc);
6656
6657         for (i = 0; i < ginst->type_argc; ++i) {
6658                 MonoType *t = ginst->type_argv [i], *norm;
6659                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6660                         is_denorm_gtd = FALSE;
6661                 norm = mono_type_normalize (t);
6662                 argv [i] = norm;
6663                 if (norm != t)
6664                         requires_rebind = TRUE;
6665         }
6666
6667         if (is_denorm_gtd)
6668                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6669
6670         if (requires_rebind) {
6671                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6672                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6673         }
6674
6675         return type;
6676 }
6677 /*
6678  * mono_type_get_object:
6679  * @domain: an app domain
6680  * @type: a type
6681  *
6682  * Return an System.MonoType object representing the type @type.
6683  */
6684 MonoReflectionType*
6685 mono_type_get_object (MonoDomain *domain, MonoType *type)
6686 {
6687         MonoType *norm_type;
6688         MonoReflectionType *res;
6689         MonoClass *klass = mono_class_from_mono_type (type);
6690
6691         /*we must avoid using @type as it might have come
6692          * from a mono_metadata_type_dup and the caller
6693          * expects that is can be freed.
6694          * Using the right type from 
6695          */
6696         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6697
6698         /* void is very common */
6699         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6700                 return (MonoReflectionType*)domain->typeof_void;
6701
6702         /*
6703          * If the vtable of the given class was already created, we can use
6704          * the MonoType from there and avoid all locking and hash table lookups.
6705          * 
6706          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6707          * that the resulting object is different.   
6708          */
6709         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6710                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6711                 if (vtable && vtable->type)
6712                         return vtable->type;
6713         }
6714
6715         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6716         mono_domain_lock (domain);
6717         if (!domain->type_hash)
6718                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6719                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6720         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6721                 mono_domain_unlock (domain);
6722                 mono_loader_unlock ();
6723                 return res;
6724         }
6725
6726         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6727          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6728          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6729          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6730          * artifact of how generics are encoded and should be transparent to managed code so we
6731          * need to weed out this diference when retrieving managed System.Type objects.
6732          */
6733         norm_type = mono_type_normalize (type);
6734         if (norm_type != type) {
6735                 res = mono_type_get_object (domain, norm_type);
6736                 mono_g_hash_table_insert (domain->type_hash, type, res);
6737                 mono_domain_unlock (domain);
6738                 mono_loader_unlock ();
6739                 return res;
6740         }
6741
6742         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6743         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6744                 g_assert (0);
6745
6746         if (!verify_safe_for_managed_space (type)) {
6747                 mono_domain_unlock (domain);
6748                 mono_loader_unlock ();
6749                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6750         }
6751
6752         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6753                 gboolean is_type_done = TRUE;
6754                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6755                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6756                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6757                 */
6758                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6759                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6760
6761                         if (gparam->owner && gparam->owner->is_method) {
6762                                 MonoMethod *method = gparam->owner->owner.method;
6763                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6764                                         is_type_done = FALSE;
6765                         } else if (gparam->owner && !gparam->owner->is_method) {
6766                                 MonoClass *klass = gparam->owner->owner.klass;
6767                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6768                                         is_type_done = FALSE;
6769                         }
6770                 } 
6771
6772                 /* g_assert_not_reached (); */
6773                 /* should this be considered an error condition? */
6774                 if (is_type_done && !type->byref) {
6775                         mono_domain_unlock (domain);
6776                         mono_loader_unlock ();
6777                         return mono_class_get_ref_info (klass);
6778                 }
6779         }
6780         /* This is stored in vtables/JITted code so it has to be pinned */
6781         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6782         res->type = type;
6783         mono_g_hash_table_insert (domain->type_hash, type, res);
6784
6785         if (type->type == MONO_TYPE_VOID)
6786                 domain->typeof_void = (MonoObject*)res;
6787
6788         mono_domain_unlock (domain);
6789         mono_loader_unlock ();
6790         return res;
6791 }
6792
6793 /*
6794  * mono_method_get_object:
6795  * @domain: an app domain
6796  * @method: a method
6797  * @refclass: the reflected type (can be NULL)
6798  *
6799  * Return an System.Reflection.MonoMethod object representing the method @method.
6800  */
6801 MonoReflectionMethod*
6802 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6803 {
6804         /*
6805          * We use the same C representation for methods and constructors, but the type 
6806          * name in C# is different.
6807          */
6808         static MonoClass *System_Reflection_MonoMethod = NULL;
6809         static MonoClass *System_Reflection_MonoCMethod = NULL;
6810         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6811         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6812         MonoClass *klass;
6813         MonoReflectionMethod *ret;
6814
6815         if (method->is_inflated) {
6816                 MonoReflectionGenericMethod *gret;
6817
6818                 refclass = method->klass;
6819                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6820                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6821                         if (!System_Reflection_MonoGenericCMethod)
6822                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6823                         klass = System_Reflection_MonoGenericCMethod;
6824                 } else {
6825                         if (!System_Reflection_MonoGenericMethod)
6826                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6827                         klass = System_Reflection_MonoGenericMethod;
6828                 }
6829                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6830                 gret->method.method = method;
6831                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6832                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6833                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6834         }
6835
6836         if (!refclass)
6837                 refclass = method->klass;
6838
6839         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6840         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6841                 if (!System_Reflection_MonoCMethod)
6842                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6843                 klass = System_Reflection_MonoCMethod;
6844         }
6845         else {
6846                 if (!System_Reflection_MonoMethod)
6847                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6848                 klass = System_Reflection_MonoMethod;
6849         }
6850         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6851         ret->method = method;
6852         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6853         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6854 }
6855
6856 /*
6857  * mono_method_clear_object:
6858  *
6859  *   Clear the cached reflection objects for the dynamic method METHOD.
6860  */
6861 void
6862 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6863 {
6864         MonoClass *klass;
6865         g_assert (method_is_dynamic (method));
6866
6867         klass = method->klass;
6868         while (klass) {
6869                 clear_cached_object (domain, method, klass);
6870                 klass = klass->parent;
6871         }
6872         /* Added by mono_param_get_objects () */
6873         clear_cached_object (domain, &(method->signature), NULL);
6874         klass = method->klass;
6875         while (klass) {
6876                 clear_cached_object (domain, &(method->signature), klass);
6877                 klass = klass->parent;
6878         }
6879 }
6880
6881 /*
6882  * mono_field_get_object:
6883  * @domain: an app domain
6884  * @klass: a type
6885  * @field: a field
6886  *
6887  * Return an System.Reflection.MonoField object representing the field @field
6888  * in class @klass.
6889  */
6890 MonoReflectionField*
6891 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6892 {
6893         MonoReflectionField *res;
6894         static MonoClass *monofield_klass;
6895
6896         CHECK_OBJECT (MonoReflectionField *, field, klass);
6897         if (!monofield_klass)
6898                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6899         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6900         res->klass = klass;
6901         res->field = field;
6902         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6903
6904         if (is_field_on_inst (field)) {
6905                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6906                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6907         } else {
6908                 if (field->type)
6909                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6910                 res->attrs = mono_field_get_flags (field);
6911         }
6912         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6913 }
6914
6915 /*
6916  * mono_property_get_object:
6917  * @domain: an app domain
6918  * @klass: a type
6919  * @property: a property
6920  *
6921  * Return an System.Reflection.MonoProperty object representing the property @property
6922  * in class @klass.
6923  */
6924 MonoReflectionProperty*
6925 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6926 {
6927         MonoReflectionProperty *res;
6928         static MonoClass *monoproperty_klass;
6929
6930         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6931         if (!monoproperty_klass)
6932                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6933         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6934         res->klass = klass;
6935         res->property = property;
6936         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6937 }
6938
6939 /*
6940  * mono_event_get_object:
6941  * @domain: an app domain
6942  * @klass: a type
6943  * @event: a event
6944  *
6945  * Return an System.Reflection.MonoEvent object representing the event @event
6946  * in class @klass.
6947  */
6948 MonoReflectionEvent*
6949 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6950 {
6951         MonoReflectionEvent *res;
6952         MonoReflectionMonoEvent *mono_event;
6953         static MonoClass *monoevent_klass;
6954
6955         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6956         if (!monoevent_klass)
6957                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6958         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6959         mono_event->klass = klass;
6960         mono_event->event = event;
6961         res = (MonoReflectionEvent*)mono_event;
6962         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6963 }
6964
6965 /**
6966  * mono_get_reflection_missing_object:
6967  * @domain: Domain where the object lives
6968  *
6969  * Returns the System.Reflection.Missing.Value singleton object
6970  * (of type System.Reflection.Missing).
6971  *
6972  * Used as the value for ParameterInfo.DefaultValue when Optional
6973  * is present
6974  */
6975 static MonoObject *
6976 mono_get_reflection_missing_object (MonoDomain *domain)
6977 {
6978         MonoObject *obj;
6979         static MonoClassField *missing_value_field = NULL;
6980         
6981         if (!missing_value_field) {
6982                 MonoClass *missing_klass;
6983                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6984                 mono_class_init (missing_klass);
6985                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6986                 g_assert (missing_value_field);
6987         }
6988         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6989         g_assert (obj);
6990         return obj;
6991 }
6992
6993 static MonoObject*
6994 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6995 {
6996         if (!*dbnull)
6997                 *dbnull = mono_get_dbnull_object (domain);
6998         return *dbnull;
6999 }
7000
7001 static MonoObject*
7002 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7003 {
7004         if (!*reflection_missing)
7005                 *reflection_missing = mono_get_reflection_missing_object (domain);
7006         return *reflection_missing;
7007 }
7008
7009 /*
7010  * mono_param_get_objects:
7011  * @domain: an app domain
7012  * @method: a method
7013  *
7014  * Return an System.Reflection.ParameterInfo array object representing the parameters
7015  * in the method @method.
7016  */
7017 MonoArray*
7018 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7019 {
7020         static MonoClass *System_Reflection_ParameterInfo;
7021         static MonoClass *System_Reflection_ParameterInfo_array;
7022         MonoError error;
7023         MonoArray *res = NULL;
7024         MonoReflectionMethod *member = NULL;
7025         MonoReflectionParameter *param = NULL;
7026         char **names, **blobs = NULL;
7027         guint32 *types = NULL;
7028         MonoType *type = NULL;
7029         MonoObject *dbnull = NULL;
7030         MonoObject *missing = NULL;
7031         MonoMarshalSpec **mspecs;
7032         MonoMethodSignature *sig;
7033         MonoVTable *pinfo_vtable;
7034         int i;
7035
7036         if (!System_Reflection_ParameterInfo_array) {
7037                 MonoClass *klass;
7038
7039                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7040                 if (!klass)
7041                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7042
7043                 mono_memory_barrier ();
7044                 System_Reflection_ParameterInfo = klass; 
7045
7046         
7047                 klass = mono_array_class_get (klass, 1);
7048                 mono_memory_barrier ();
7049                 System_Reflection_ParameterInfo_array = klass;
7050         }
7051
7052         sig = mono_method_signature_checked (method, &error);
7053         if (!mono_error_ok (&error))
7054                 mono_error_raise_exception (&error);
7055
7056         if (!sig->param_count)
7057                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
7058
7059         /* Note: the cache is based on the address of the signature into the method
7060          * since we already cache MethodInfos with the method as keys.
7061          */
7062         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7063
7064         member = mono_method_get_object (domain, method, refclass);
7065         names = g_new (char *, sig->param_count);
7066         mono_method_get_param_names (method, (const char **) names);
7067
7068         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7069         mono_method_get_marshal_info (method, mspecs);
7070
7071         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
7072         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7073         for (i = 0; i < sig->param_count; ++i) {
7074                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
7075                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7076                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7077                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7078                 param->PositionImpl = i;
7079                 param->AttrsImpl = sig->params [i]->attrs;
7080
7081                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7082                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7083                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7084                         else
7085                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7086                 } else {
7087
7088                         if (!blobs) {
7089                                 blobs = g_new0 (char *, sig->param_count);
7090                                 types = g_new0 (guint32, sig->param_count);
7091                                 get_default_param_value_blobs (method, blobs, types); 
7092                         }
7093
7094                         /* Build MonoType for the type from the Constant Table */
7095                         if (!type)
7096                                 type = g_new0 (MonoType, 1);
7097                         type->type = types [i];
7098                         type->data.klass = NULL;
7099                         if (types [i] == MONO_TYPE_CLASS)
7100                                 type->data.klass = mono_defaults.object_class;
7101                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7102                                 /* For enums, types [i] contains the base type */
7103
7104                                         type->type = MONO_TYPE_VALUETYPE;
7105                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7106                         } else
7107                                 type->data.klass = mono_class_from_mono_type (type);
7108
7109                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7110
7111                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7112                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7113                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7114                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7115                                 else
7116                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7117                         }
7118                         
7119                 }
7120
7121                 if (mspecs [i + 1])
7122                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7123                 
7124                 mono_array_setref (res, i, param);
7125         }
7126         g_free (names);
7127         g_free (blobs);
7128         g_free (types);
7129         g_free (type);
7130
7131         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7132                 if (mspecs [i])
7133                         mono_metadata_free_marshal_spec (mspecs [i]);
7134         g_free (mspecs);
7135         
7136         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7137 }
7138
7139 MonoArray*
7140 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7141 {
7142         return mono_param_get_objects_internal (domain, method, NULL);
7143 }
7144
7145 /*
7146  * mono_method_body_get_object:
7147  * @domain: an app domain
7148  * @method: a method
7149  *
7150  * Return an System.Reflection.MethodBody object representing the method @method.
7151  */
7152 MonoReflectionMethodBody*
7153 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7154 {
7155         static MonoClass *System_Reflection_MethodBody = NULL;
7156         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7157         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7158         MonoReflectionMethodBody *ret;
7159         MonoMethodHeader *header;
7160         MonoImage *image;
7161         guint32 method_rva, local_var_sig_token;
7162     char *ptr;
7163         unsigned char format, flags;
7164         int i;
7165
7166         /* for compatibility with .net */
7167     if (method_is_dynamic (method))
7168         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7169
7170         if (!System_Reflection_MethodBody)
7171                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7172         if (!System_Reflection_LocalVariableInfo)
7173                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7174         if (!System_Reflection_ExceptionHandlingClause)
7175                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7176
7177         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7178
7179         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7180                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7181             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7182                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7183             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7184                 return NULL;
7185
7186         image = method->klass->image;
7187         header = mono_method_get_header (method);
7188
7189         if (!image_is_dynamic (image)) {
7190                 /* Obtain local vars signature token */
7191                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7192                 ptr = mono_image_rva_map (image, method_rva);
7193                 flags = *(const unsigned char *) ptr;
7194                 format = flags & METHOD_HEADER_FORMAT_MASK;
7195                 switch (format){
7196                 case METHOD_HEADER_TINY_FORMAT:
7197                         local_var_sig_token = 0;
7198                         break;
7199                 case METHOD_HEADER_FAT_FORMAT:
7200                         ptr += 2;
7201                         ptr += 2;
7202                         ptr += 4;
7203                         local_var_sig_token = read32 (ptr);
7204                         break;
7205                 default:
7206                         g_assert_not_reached ();
7207                 }
7208         } else
7209                 local_var_sig_token = 0; //FIXME
7210
7211         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7212
7213         ret->init_locals = header->init_locals;
7214         ret->max_stack = header->max_stack;
7215         ret->local_var_sig_token = local_var_sig_token;
7216         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7217         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7218
7219         /* Locals */
7220         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7221         for (i = 0; i < header->num_locals; ++i) {
7222                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7223                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7224                 info->is_pinned = header->locals [i]->pinned;
7225                 info->local_index = i;
7226                 mono_array_setref (ret->locals, i, info);
7227         }
7228
7229         /* Exceptions */
7230         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7231         for (i = 0; i < header->num_clauses; ++i) {
7232                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7233                 MonoExceptionClause *clause = &header->clauses [i];
7234
7235                 info->flags = clause->flags;
7236                 info->try_offset = clause->try_offset;
7237                 info->try_length = clause->try_len;
7238                 info->handler_offset = clause->handler_offset;
7239                 info->handler_length = clause->handler_len;
7240                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7241                         info->filter_offset = clause->data.filter_offset;
7242                 else if (clause->data.catch_class)
7243                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7244
7245                 mono_array_setref (ret->clauses, i, info);
7246         }
7247
7248         mono_metadata_free_mh (header);
7249         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7250         return ret;
7251 }
7252
7253 /**
7254  * mono_get_dbnull_object:
7255  * @domain: Domain where the object lives
7256  *
7257  * Returns the System.DBNull.Value singleton object
7258  *
7259  * Used as the value for ParameterInfo.DefaultValue 
7260  */
7261 MonoObject *
7262 mono_get_dbnull_object (MonoDomain *domain)
7263 {
7264         MonoObject *obj;
7265         static MonoClassField *dbnull_value_field = NULL;
7266         
7267         if (!dbnull_value_field) {
7268                 MonoClass *dbnull_klass;
7269                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7270                 mono_class_init (dbnull_klass);
7271                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7272                 g_assert (dbnull_value_field);
7273         }
7274         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7275         g_assert (obj);
7276         return obj;
7277 }
7278
7279 static void
7280 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7281 {
7282         guint32 param_index, i, lastp, crow = 0;
7283         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7284         gint32 idx;
7285
7286         MonoClass *klass = method->klass;
7287         MonoImage *image = klass->image;
7288         MonoMethodSignature *methodsig = mono_method_signature (method);
7289
7290         MonoTableInfo *constt;
7291         MonoTableInfo *methodt;
7292         MonoTableInfo *paramt;
7293
7294         if (!methodsig->param_count)
7295                 return;
7296
7297         mono_class_init (klass);
7298
7299         if (image_is_dynamic (klass->image)) {
7300                 MonoReflectionMethodAux *aux;
7301                 if (method->is_inflated)
7302                         method = ((MonoMethodInflated*)method)->declaring;
7303                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7304                 if (aux && aux->param_defaults) {
7305                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7306                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7307                 }
7308                 return;
7309         }
7310
7311         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7312         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7313         constt = &image->tables [MONO_TABLE_CONSTANT];
7314
7315         idx = mono_method_get_index (method) - 1;
7316         g_assert (idx != -1);
7317
7318         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7319         if (idx + 1 < methodt->rows)
7320                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7321         else
7322                 lastp = paramt->rows + 1;
7323
7324         for (i = param_index; i < lastp; ++i) {
7325                 guint32 paramseq;
7326
7327                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7328                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7329
7330                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7331                         continue;
7332
7333                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7334                 if (!crow) {
7335                         continue;
7336                 }
7337         
7338                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7339                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7340                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7341         }
7342
7343         return;
7344 }
7345
7346 MonoObject *
7347 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7348 {
7349         void *retval;
7350         MonoClass *klass;
7351         MonoObject *object;
7352         MonoType *basetype = type;
7353
7354         if (!blob)
7355                 return NULL;
7356         
7357         klass = mono_class_from_mono_type (type);
7358         if (klass->valuetype) {
7359                 object = mono_object_new (domain, klass);
7360                 retval = ((gchar *) object + sizeof (MonoObject));
7361                 if (klass->enumtype)
7362                         basetype = mono_class_enum_basetype (klass);
7363         } else {
7364                 retval = &object;
7365         }
7366                         
7367         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7368                 return object;
7369         else
7370                 return NULL;
7371 }
7372
7373 static int
7374 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7375         int found_sep;
7376         char *s;
7377         gboolean quoted = FALSE;
7378
7379         memset (assembly, 0, sizeof (MonoAssemblyName));
7380         assembly->culture = "";
7381         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7382
7383         if (*p == '"') {
7384                 quoted = TRUE;
7385                 p++;
7386         }
7387         assembly->name = p;
7388         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7389                 p++;
7390         if (quoted) {
7391                 if (*p != '"')
7392                         return 1;
7393                 *p = 0;
7394                 p++;
7395         }
7396         if (*p != ',')
7397                 return 1;
7398         *p = 0;
7399         /* Remove trailing whitespace */
7400         s = p - 1;
7401         while (*s && g_ascii_isspace (*s))
7402                 *s-- = 0;
7403         p ++;
7404         while (g_ascii_isspace (*p))
7405                 p++;
7406         while (*p) {
7407                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7408                         p += 8;
7409                         assembly->major = strtoul (p, &s, 10);
7410                         if (s == p || *s != '.')
7411                                 return 1;
7412                         p = ++s;
7413                         assembly->minor = strtoul (p, &s, 10);
7414                         if (s == p || *s != '.')
7415                                 return 1;
7416                         p = ++s;
7417                         assembly->build = strtoul (p, &s, 10);
7418                         if (s == p || *s != '.')
7419                                 return 1;
7420                         p = ++s;
7421                         assembly->revision = strtoul (p, &s, 10);
7422                         if (s == p)
7423                                 return 1;
7424                         p = s;
7425                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7426                         p += 8;
7427                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7428                                 assembly->culture = "";
7429                                 p += 7;
7430                         } else {
7431                                 assembly->culture = p;
7432                                 while (*p && *p != ',') {
7433                                         p++;
7434                                 }
7435                         }
7436                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7437                         p += 15;
7438                         if (strncmp (p, "null", 4) == 0) {
7439                                 p += 4;
7440                         } else {
7441                                 int len;
7442                                 gchar *start = p;
7443                                 while (*p && *p != ',') {
7444                                         p++;
7445                                 }
7446                                 len = (p - start + 1);
7447                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7448                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7449                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7450                         }
7451                 } else {
7452                         while (*p && *p != ',')
7453                                 p++;
7454                 }
7455                 found_sep = 0;
7456                 while (g_ascii_isspace (*p) || *p == ',') {
7457                         *p++ = 0;
7458                         found_sep = 1;
7459                         continue;
7460                 }
7461                 /* failed */
7462                 if (!found_sep)
7463                         return 1;
7464         }
7465
7466         return 0;
7467 }
7468
7469 /*
7470  * mono_reflection_parse_type:
7471  * @name: type name
7472  *
7473  * Parse a type name as accepted by the GetType () method and output the info
7474  * extracted in the info structure.
7475  * the name param will be mangled, so, make a copy before passing it to this function.
7476  * The fields in info will be valid until the memory pointed to by name is valid.
7477  *
7478  * See also mono_type_get_name () below.
7479  *
7480  * Returns: 0 on parse error.
7481  */
7482 static int
7483 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7484                              MonoTypeNameParse *info)
7485 {
7486         char *start, *p, *w, *last_point, *startn;
7487         int in_modifiers = 0;
7488         int isbyref = 0, rank = 0, isptr = 0;
7489
7490         start = p = w = name;
7491
7492         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7493         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7494         info->name = info->name_space = NULL;
7495         info->nested = NULL;
7496         info->modifiers = NULL;
7497         info->type_arguments = NULL;
7498
7499         /* last_point separates the namespace from the name */
7500         last_point = NULL;
7501         /* Skips spaces */
7502         while (*p == ' ') p++, start++, w++, name++;
7503
7504         while (*p) {
7505                 switch (*p) {
7506                 case '+':
7507                         *p = 0; /* NULL terminate the name */
7508                         startn = p + 1;
7509                         info->nested = g_list_append (info->nested, startn);
7510                         /* we have parsed the nesting namespace + name */
7511                         if (info->name)
7512                                 break;
7513                         if (last_point) {
7514                                 info->name_space = start;
7515                                 *last_point = 0;
7516                                 info->name = last_point + 1;
7517                         } else {
7518                                 info->name_space = (char *)"";
7519                                 info->name = start;
7520                         }
7521                         break;
7522                 case '.':
7523                         last_point = p;
7524                         break;
7525                 case '\\':
7526                         ++p;
7527                         break;
7528                 case '&':
7529                 case '*':
7530                 case '[':
7531                 case ',':
7532                 case ']':
7533                         in_modifiers = 1;
7534                         break;
7535                 default:
7536                         break;
7537                 }
7538                 if (in_modifiers)
7539                         break;
7540                 // *w++ = *p++;
7541                 p++;
7542         }
7543         
7544         if (!info->name) {
7545                 if (last_point) {
7546                         info->name_space = start;
7547                         *last_point = 0;
7548                         info->name = last_point + 1;
7549                 } else {
7550                         info->name_space = (char *)"";
7551                         info->name = start;
7552                 }
7553         }
7554         while (*p) {
7555                 switch (*p) {
7556                 case '&':
7557                         if (isbyref) /* only one level allowed by the spec */
7558                                 return 0;
7559                         isbyref = 1;
7560                         isptr = 0;
7561                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7562                         *p++ = 0;
7563                         break;
7564                 case '*':
7565                         if (isbyref) /* pointer to ref not okay */
7566                                 return 0;
7567                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7568                         isptr = 1;
7569                         *p++ = 0;
7570                         break;
7571                 case '[':
7572                         if (isbyref) /* array of ref and generic ref are not okay */
7573                                 return 0;
7574                         //Decide if it's an array of a generic argument list
7575                         *p++ = 0;
7576
7577                         if (!*p) //XXX test
7578                                 return 0;
7579                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7580                                 isptr = 0;
7581                                 rank = 1;
7582                                 while (*p) {
7583                                         if (*p == ']')
7584                                                 break;
7585                                         if (*p == ',')
7586                                                 rank++;
7587                                         else if (*p == '*') /* '*' means unknown lower bound */
7588                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7589                                         else
7590                                                 return 0;
7591                                         ++p;
7592                                 }
7593                                 if (*p++ != ']')
7594                                         return 0;
7595                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7596                         } else {
7597                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7598                                         return 0;
7599                                 isptr = 0;
7600                                 info->type_arguments = g_ptr_array_new ();
7601                                 while (*p) {
7602                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7603                                         gboolean fqname = FALSE;
7604
7605                                         g_ptr_array_add (info->type_arguments, subinfo);
7606
7607                                         while (*p == ' ') p++;
7608                                         if (*p == '[') {
7609                                                 p++;
7610                                                 fqname = TRUE;
7611                                         }
7612
7613                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7614                                                 return 0;
7615
7616                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7617                                         if (fqname && (*p != ']')) {
7618                                                 char *aname;
7619
7620                                                 if (*p != ',')
7621                                                         return 0;
7622                                                 *p++ = 0;
7623
7624                                                 aname = p;
7625                                                 while (*p && (*p != ']'))
7626                                                         p++;
7627
7628                                                 if (*p != ']')
7629                                                         return 0;
7630
7631                                                 *p++ = 0;
7632                                                 while (*aname) {
7633                                                         if (g_ascii_isspace (*aname)) {
7634                                                                 ++aname;
7635                                                                 continue;
7636                                                         }
7637                                                         break;
7638                                                 }
7639                                                 if (!*aname ||
7640                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7641                                                         return 0;
7642                                         } else if (fqname && (*p == ']')) {
7643                                                 *p++ = 0;
7644                                         }
7645                                         if (*p == ']') {
7646                                                 *p++ = 0;
7647                                                 break;
7648                                         } else if (!*p) {
7649                                                 return 0;
7650                                         }
7651                                         *p++ = 0;
7652                                 }
7653                         }
7654                         break;
7655                 case ']':
7656                         if (is_recursed)
7657                                 goto end;
7658                         return 0;
7659                 case ',':
7660                         if (is_recursed)
7661                                 goto end;
7662                         *p++ = 0;
7663                         while (*p) {
7664                                 if (g_ascii_isspace (*p)) {
7665                                         ++p;
7666                                         continue;
7667                                 }
7668                                 break;
7669                         }
7670                         if (!*p)
7671                                 return 0; /* missing assembly name */
7672                         if (!assembly_name_to_aname (&info->assembly, p))
7673                                 return 0;
7674                         break;
7675                 default:
7676                         return 0;
7677                 }
7678                 if (info->assembly.name)
7679                         break;
7680         }
7681         // *w = 0; /* terminate class name */
7682  end:
7683         if (!info->name || !*info->name)
7684                 return 0;
7685         if (endptr)
7686                 *endptr = p;
7687         /* add other consistency checks */
7688         return 1;
7689 }
7690
7691
7692 /**
7693  * mono_identifier_unescape_type_name_chars:
7694  * @identifier: the display name of a mono type
7695  *
7696  * Returns:
7697  *  The name in internal form, that is without escaping backslashes.
7698  *
7699  *  The string is modified in place!
7700  */
7701 char*
7702 mono_identifier_unescape_type_name_chars(char* identifier)
7703 {
7704         char *w, *r;
7705         if (!identifier)
7706                 return NULL;
7707         for (w = r = identifier; *r != 0; r++)
7708         {
7709                 char c = *r;
7710                 if (c == '\\') {
7711                         r++;
7712                         if (*r == 0)
7713                                 break;
7714                         c = *r;
7715                 }
7716                 *w = c;
7717                 w++;
7718         }
7719         if (w != r)
7720                 *w = 0;
7721         return identifier;
7722 }
7723
7724 void
7725 mono_identifier_unescape_info (MonoTypeNameParse* info);
7726
7727 static void
7728 unescape_each_type_argument(void* data, void* user_data)
7729 {
7730         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7731         mono_identifier_unescape_info (info);
7732 }
7733
7734 static void
7735 unescape_each_nested_name (void* data, void* user_data)
7736 {
7737         char* nested_name = (char*) data;
7738         mono_identifier_unescape_type_name_chars(nested_name);
7739 }
7740
7741 /**
7742  * mono_identifier_unescape_info:
7743  *
7744  * @info: a parsed display form of an (optionally assembly qualified) full type name.
7745  *
7746  * Returns: nothing.
7747  *
7748  * Destructively updates the info by unescaping the identifiers that
7749  * comprise the type namespace, name, nested types (if any) and
7750  * generic type arguments (if any).
7751  *
7752  * The resulting info has the names in internal form.
7753  *
7754  */
7755 void
7756 mono_identifier_unescape_info (MonoTypeNameParse *info)
7757 {
7758         if (!info)
7759                 return;
7760         mono_identifier_unescape_type_name_chars(info->name_space);
7761         mono_identifier_unescape_type_name_chars(info->name);
7762         // but don't escape info->assembly
7763         if (info->type_arguments)
7764                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7765         if (info->nested)
7766                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7767 }
7768
7769 int
7770 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7771 {
7772         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7773         if (ok) {
7774                 mono_identifier_unescape_info (info);
7775         }
7776         return ok;
7777 }
7778
7779 static MonoType*
7780 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7781 {
7782         gboolean type_resolve = FALSE;
7783         MonoType *type;
7784         MonoImage *rootimage = image;
7785
7786         if (info->assembly.name) {
7787                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7788                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7789                         /* 
7790                          * This could happen in the AOT compiler case when the search hook is not
7791                          * installed.
7792                          */
7793                         assembly = image->assembly;
7794                 if (!assembly) {
7795                         /* then we must load the assembly ourselve - see #60439 */
7796                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7797                         if (!assembly)
7798                                 return NULL;
7799                 }
7800                 image = assembly->image;
7801         } else if (!image) {
7802                 image = mono_defaults.corlib;
7803         }
7804
7805         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7806         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7807                 image = mono_defaults.corlib;
7808                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7809         }
7810
7811         return type;
7812 }
7813
7814 static MonoType*
7815 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7816 {
7817         MonoClass *klass;
7818         GList *mod;
7819         int modval;
7820         gboolean bounded = FALSE;
7821         
7822         if (!image)
7823                 image = mono_defaults.corlib;
7824
7825         if (!rootimage)
7826                 rootimage = mono_defaults.corlib;
7827
7828         if (ignorecase) {
7829                 MonoError error;
7830                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7831                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7832         } else {
7833                 klass = mono_class_from_name (image, info->name_space, info->name);
7834         }
7835         if (!klass)
7836                 return NULL;
7837         for (mod = info->nested; mod; mod = mod->next) {
7838                 gpointer iter = NULL;
7839                 MonoClass *parent;
7840
7841                 parent = klass;
7842                 mono_class_init (parent);
7843
7844                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7845                         char *lastp;
7846                         char *nested_name, *nested_nspace;
7847                         gboolean match = TRUE;
7848
7849                         lastp = strrchr (mod->data, '.');
7850                         if (lastp) {
7851                                 /* Nested classes can have namespaces */
7852                                 int nspace_len;
7853
7854                                 nested_name = g_strdup (lastp + 1);
7855                                 nspace_len = lastp - (char*)mod->data;
7856                                 nested_nspace = g_malloc (nspace_len + 1);
7857                                 memcpy (nested_nspace, mod->data, nspace_len);
7858                                 nested_nspace [nspace_len] = '\0';
7859
7860                         } else {
7861                                 nested_name = mod->data;
7862                                 nested_nspace = NULL;
7863                         }
7864
7865                         if (nested_nspace) {
7866                                 if (ignorecase) {
7867                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7868                                                 match = FALSE;
7869                                 } else {
7870                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7871                                                 match = FALSE;
7872                                 }
7873                         }
7874                         if (match) {
7875                                 if (ignorecase) {
7876                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7877                                                 match = FALSE;
7878                                 } else {
7879                                         if (strcmp (klass->name, nested_name) != 0)
7880                                                 match = FALSE;
7881                                 }
7882                         }
7883                         if (lastp) {
7884                                 g_free (nested_name);
7885                                 g_free (nested_nspace);
7886                         }
7887                         if (match)
7888                                 break;
7889                 }
7890
7891                 if (!klass)
7892                         break;
7893         }
7894         if (!klass)
7895                 return NULL;
7896
7897         if (info->type_arguments) {
7898                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7899                 MonoReflectionType *the_type;
7900                 MonoType *instance;
7901                 int i;
7902
7903                 for (i = 0; i < info->type_arguments->len; i++) {
7904                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7905
7906                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7907                         if (!type_args [i]) {
7908                                 g_free (type_args);
7909                                 return NULL;
7910                         }
7911                 }
7912
7913                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7914
7915                 instance = mono_reflection_bind_generic_parameters (
7916                         the_type, info->type_arguments->len, type_args);
7917
7918                 g_free (type_args);
7919                 if (!instance)
7920                         return NULL;
7921
7922                 klass = mono_class_from_mono_type (instance);
7923         }
7924
7925         for (mod = info->modifiers; mod; mod = mod->next) {
7926                 modval = GPOINTER_TO_UINT (mod->data);
7927                 if (!modval) { /* byref: must be last modifier */
7928                         return &klass->this_arg;
7929                 } else if (modval == -1) {
7930                         klass = mono_ptr_class_get (&klass->byval_arg);
7931                 } else if (modval == -2) {
7932                         bounded = TRUE;
7933                 } else { /* array rank */
7934                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7935                 }
7936         }
7937
7938         return &klass->byval_arg;
7939 }
7940
7941 /*
7942  * mono_reflection_get_type:
7943  * @image: a metadata context
7944  * @info: type description structure
7945  * @ignorecase: flag for case-insensitive string compares
7946  * @type_resolve: whenever type resolve was already tried
7947  *
7948  * Build a MonoType from the type description in @info.
7949  * 
7950  */
7951
7952 MonoType*
7953 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7954         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7955 }
7956
7957 static MonoType*
7958 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7959 {
7960         MonoReflectionAssemblyBuilder *abuilder;
7961         MonoType *type;
7962         int i;
7963
7964         g_assert (assembly_is_dynamic (assembly));
7965         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7966
7967         /* Enumerate all modules */
7968
7969         type = NULL;
7970         if (abuilder->modules) {
7971                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7972                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7973                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7974                         if (type)
7975                                 break;
7976                 }
7977         }
7978
7979         if (!type && abuilder->loaded_modules) {
7980                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7981                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7982                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7983                         if (type)
7984                                 break;
7985                 }
7986         }
7987
7988         return type;
7989 }
7990         
7991 MonoType*
7992 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7993 {
7994         MonoType *type;
7995         MonoReflectionAssembly *assembly;
7996         GString *fullName;
7997         GList *mod;
7998
7999         if (image && image_is_dynamic (image))
8000                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8001         else
8002                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8003         if (type)
8004                 return type;
8005         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8006                 return NULL;
8007
8008         if (type_resolve) {
8009                 if (*type_resolve) 
8010                         return NULL;
8011                 else
8012                         *type_resolve = TRUE;
8013         }
8014         
8015         /* Reconstruct the type name */
8016         fullName = g_string_new ("");
8017         if (info->name_space && (info->name_space [0] != '\0'))
8018                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8019         else
8020                 g_string_printf (fullName, "%s", info->name);
8021         for (mod = info->nested; mod; mod = mod->next)
8022                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8023
8024         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8025         if (assembly) {
8026                 if (assembly_is_dynamic (assembly->assembly))
8027                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8028                 else
8029                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8030                                                                                                           info, ignorecase);
8031         }
8032         g_string_free (fullName, TRUE);
8033         return type;
8034 }
8035
8036 void
8037 mono_reflection_free_type_info (MonoTypeNameParse *info)
8038 {
8039         g_list_free (info->modifiers);
8040         g_list_free (info->nested);
8041
8042         if (info->type_arguments) {
8043                 int i;
8044
8045                 for (i = 0; i < info->type_arguments->len; i++) {
8046                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
8047
8048                         mono_reflection_free_type_info (subinfo);
8049                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8050                         g_free (subinfo);
8051                 }
8052
8053                 g_ptr_array_free (info->type_arguments, TRUE);
8054         }
8055 }
8056
8057 /*
8058  * mono_reflection_type_from_name:
8059  * @name: type name.
8060  * @image: a metadata context (can be NULL).
8061  *
8062  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8063  * it defaults to get the type from @image or, if @image is NULL or loading
8064  * from it fails, uses corlib.
8065  * 
8066  */
8067 MonoType*
8068 mono_reflection_type_from_name (char *name, MonoImage *image)
8069 {
8070         MonoType *type = NULL;
8071         MonoTypeNameParse info;
8072         char *tmp;
8073
8074         /* Make a copy since parse_type modifies its argument */
8075         tmp = g_strdup (name);
8076         
8077         /*g_print ("requested type %s\n", str);*/
8078         if (mono_reflection_parse_type (tmp, &info)) {
8079                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8080         }
8081
8082         g_free (tmp);
8083         mono_reflection_free_type_info (&info);
8084         return type;
8085 }
8086
8087 /*
8088  * mono_reflection_get_token:
8089  *
8090  *   Return the metadata token of OBJ which should be an object
8091  * representing a metadata element.
8092  */
8093 guint32
8094 mono_reflection_get_token (MonoObject *obj)
8095 {
8096         MonoClass *klass;
8097         guint32 token = 0;
8098
8099         klass = obj->vtable->klass;
8100
8101         if (strcmp (klass->name, "MethodBuilder") == 0) {
8102                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8103
8104                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8105         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8106                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8107
8108                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8109         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8110                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8111
8112                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8113         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8114                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8115                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8116         } else if (strcmp (klass->name, "MonoType") == 0) {
8117                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8118                 MonoClass *mc = mono_class_from_mono_type (type);
8119                 if (!mono_class_init (mc))
8120                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8121
8122                 token = mc->type_token;
8123         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8124                    strcmp (klass->name, "MonoMethod") == 0 ||
8125                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8126                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8127                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8128                 if (m->method->is_inflated) {
8129                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8130                         return inflated->declaring->token;
8131                 } else {
8132                         token = m->method->token;
8133                 }
8134         } else if (strcmp (klass->name, "MonoField") == 0) {
8135                 MonoReflectionField *f = (MonoReflectionField*)obj;
8136
8137                 if (is_field_on_inst (f->field)) {
8138                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8139
8140                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8141                                 int field_index = f->field - dgclass->fields;
8142                                 MonoObject *obj;
8143
8144                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8145                                 obj = dgclass->field_objects [field_index];
8146                                 return mono_reflection_get_token (obj);
8147                         }
8148                 }
8149                 token = mono_class_get_field_token (f->field);
8150         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8151                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8152
8153                 token = mono_class_get_property_token (p->property);
8154         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8155                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8156
8157                 token = mono_class_get_event_token (p->event);
8158         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8159                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8160                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8161                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8162
8163                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8164         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8165                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8166
8167                 token = m->token;
8168         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8169                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8170         } else {
8171                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8172                 MonoException *ex = mono_get_exception_not_implemented (msg);
8173                 g_free (msg);
8174                 mono_raise_exception (ex);
8175         }
8176
8177         return token;
8178 }
8179
8180 static MonoClass*
8181 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8182 {
8183         char *n;
8184         MonoType *t;
8185         int slen = mono_metadata_decode_value (p, &p);
8186
8187         mono_error_init (error);
8188
8189         n = g_memdup (p, slen + 1);
8190         n [slen] = 0;
8191         t = mono_reflection_type_from_name (n, image);
8192         if (!t) {
8193                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8194                 /* We don't free n, it's consumed by mono_error */
8195                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8196                 return NULL;
8197         }
8198         g_free (n);
8199         p += slen;
8200         *end = p;
8201         return mono_class_from_mono_type (t);
8202 }
8203
8204 static void*
8205 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8206 {
8207         int slen, type = t->type;
8208         MonoClass *tklass = t->data.klass;
8209
8210         mono_error_init (error);
8211
8212 handle_enum:
8213         switch (type) {
8214         case MONO_TYPE_U1:
8215         case MONO_TYPE_I1:
8216         case MONO_TYPE_BOOLEAN: {
8217                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8218                 *bval = *p;
8219                 *end = p + 1;
8220                 return bval;
8221         }
8222         case MONO_TYPE_CHAR:
8223         case MONO_TYPE_U2:
8224         case MONO_TYPE_I2: {
8225                 guint16 *val = g_malloc (sizeof (guint16));
8226                 *val = read16 (p);
8227                 *end = p + 2;
8228                 return val;
8229         }
8230 #if SIZEOF_VOID_P == 4
8231         case MONO_TYPE_U:
8232         case MONO_TYPE_I:
8233 #endif
8234         case MONO_TYPE_R4:
8235         case MONO_TYPE_U4:
8236         case MONO_TYPE_I4: {
8237                 guint32 *val = g_malloc (sizeof (guint32));
8238                 *val = read32 (p);
8239                 *end = p + 4;
8240                 return val;
8241         }
8242 #if SIZEOF_VOID_P == 8
8243         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8244         case MONO_TYPE_I:
8245 #endif
8246         case MONO_TYPE_U8:
8247         case MONO_TYPE_I8: {
8248                 guint64 *val = g_malloc (sizeof (guint64));
8249                 *val = read64 (p);
8250                 *end = p + 8;
8251                 return val;
8252         }
8253         case MONO_TYPE_R8: {
8254                 double *val = g_malloc (sizeof (double));
8255                 readr8 (p, val);
8256                 *end = p + 8;
8257                 return val;
8258         }
8259         case MONO_TYPE_VALUETYPE:
8260                 if (t->data.klass->enumtype) {
8261                         type = mono_class_enum_basetype (t->data.klass)->type;
8262                         goto handle_enum;
8263                 } else {
8264                         MonoClass *k =  t->data.klass;
8265                         
8266                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8267                                 guint64 *val = g_malloc (sizeof (guint64));
8268                                 *val = read64 (p);
8269                                 *end = p + 8;
8270                                 return val;
8271                         }
8272                 }
8273                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8274                 break;
8275                 
8276         case MONO_TYPE_STRING:
8277                 if (*p == (char)0xFF) {
8278                         *end = p + 1;
8279                         return NULL;
8280                 }
8281                 slen = mono_metadata_decode_value (p, &p);
8282                 *end = p + slen;
8283                 return mono_string_new_len (mono_domain_get (), p, slen);
8284         case MONO_TYPE_CLASS: {
8285                 char *n;
8286                 MonoType *t;
8287                 if (*p == (char)0xFF) {
8288                         *end = p + 1;
8289                         return NULL;
8290                 }
8291 handle_type:
8292                 slen = mono_metadata_decode_value (p, &p);
8293                 n = g_memdup (p, slen + 1);
8294                 n [slen] = 0;
8295                 t = mono_reflection_type_from_name (n, image);
8296                 if (!t) {
8297                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8298                         /* We don't free n, it's consumed by mono_error */
8299                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8300                         return NULL;
8301                 }
8302                 g_free (n);
8303                 *end = p + slen;
8304                 return mono_type_get_object (mono_domain_get (), t);
8305         }
8306         case MONO_TYPE_OBJECT: {
8307                 char subt = *p++;
8308                 MonoObject *obj;
8309                 MonoClass *subc = NULL;
8310                 void *val;
8311
8312                 if (subt == 0x50) {
8313                         goto handle_type;
8314                 } else if (subt == 0x0E) {
8315                         type = MONO_TYPE_STRING;
8316                         goto handle_enum;
8317                 } else if (subt == 0x1D) {
8318                         MonoType simple_type = {{0}};
8319                         int etype = *p;
8320                         p ++;
8321
8322                         type = MONO_TYPE_SZARRAY;
8323                         if (etype == 0x50) {
8324                                 tklass = mono_defaults.systemtype_class;
8325                         } else if (etype == 0x55) {
8326                                 tklass = load_cattr_enum_type (image, p, &p, error);
8327                                 if (!mono_error_ok (error))
8328                                         return NULL;
8329                         } else {
8330                                 if (etype == 0x51)
8331                                         /* See Partition II, Appendix B3 */
8332                                         etype = MONO_TYPE_OBJECT;
8333                                 simple_type.type = etype;
8334                                 tklass = mono_class_from_mono_type (&simple_type);
8335                         }
8336                         goto handle_enum;
8337                 } else if (subt == 0x55) {
8338                         char *n;
8339                         MonoType *t;
8340                         slen = mono_metadata_decode_value (p, &p);
8341                         n = g_memdup (p, slen + 1);
8342                         n [slen] = 0;
8343                         t = mono_reflection_type_from_name (n, image);
8344                         if (!t) {
8345                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8346                                 /* We don't free n, it's consumed by mono_error */
8347                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8348                                 return NULL;
8349                         }
8350                         g_free (n);
8351                         p += slen;
8352                         subc = mono_class_from_mono_type (t);
8353                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8354                         MonoType simple_type = {{0}};
8355                         simple_type.type = subt;
8356                         subc = mono_class_from_mono_type (&simple_type);
8357                 } else {
8358                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8359                 }
8360                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8361                 obj = NULL;
8362                 if (mono_error_ok (error)) {
8363                         obj = mono_object_new (mono_domain_get (), subc);
8364                         g_assert (!subc->has_references);
8365                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8366                 }
8367
8368                 g_free (val);
8369                 return obj;
8370         }
8371         case MONO_TYPE_SZARRAY: {
8372                 MonoArray *arr;
8373                 guint32 i, alen, basetype;
8374                 alen = read32 (p);
8375                 p += 4;
8376                 if (alen == 0xffffffff) {
8377                         *end = p;
8378                         return NULL;
8379                 }
8380                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8381                 basetype = tklass->byval_arg.type;
8382                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8383                         basetype = mono_class_enum_basetype (tklass)->type;
8384                 switch (basetype)
8385                 {
8386                         case MONO_TYPE_U1:
8387                         case MONO_TYPE_I1:
8388                         case MONO_TYPE_BOOLEAN:
8389                                 for (i = 0; i < alen; i++) {
8390                                         MonoBoolean val = *p++;
8391                                         mono_array_set (arr, MonoBoolean, i, val);
8392                                 }
8393                                 break;
8394                         case MONO_TYPE_CHAR:
8395                         case MONO_TYPE_U2:
8396                         case MONO_TYPE_I2:
8397                                 for (i = 0; i < alen; i++) {
8398                                         guint16 val = read16 (p);
8399                                         mono_array_set (arr, guint16, i, val);
8400                                         p += 2;
8401                                 }
8402                                 break;
8403                         case MONO_TYPE_R4:
8404                         case MONO_TYPE_U4:
8405                         case MONO_TYPE_I4:
8406                                 for (i = 0; i < alen; i++) {
8407                                         guint32 val = read32 (p);
8408                                         mono_array_set (arr, guint32, i, val);
8409                                         p += 4;
8410                                 }
8411                                 break;
8412                         case MONO_TYPE_R8:
8413                                 for (i = 0; i < alen; i++) {
8414                                         double val;
8415                                         readr8 (p, &val);
8416                                         mono_array_set (arr, double, i, val);
8417                                         p += 8;
8418                                 }
8419                                 break;
8420                         case MONO_TYPE_U8:
8421                         case MONO_TYPE_I8:
8422                                 for (i = 0; i < alen; i++) {
8423                                         guint64 val = read64 (p);
8424                                         mono_array_set (arr, guint64, i, val);
8425                                         p += 8;
8426                                 }
8427                                 break;
8428                         case MONO_TYPE_CLASS:
8429                         case MONO_TYPE_OBJECT:
8430                         case MONO_TYPE_STRING:
8431                         case MONO_TYPE_SZARRAY:
8432                                 for (i = 0; i < alen; i++) {
8433                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8434                                         if (!mono_error_ok (error))
8435                                                 return NULL;
8436                                         mono_array_setref (arr, i, item);
8437                                 }
8438                                 break;
8439                         default:
8440                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8441                 }
8442                 *end=p;
8443                 return arr;
8444         }
8445         default:
8446                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8447         }
8448         return NULL;
8449 }
8450
8451 static MonoObject*
8452 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8453 {
8454         static MonoClass *klass;
8455         static MonoMethod *ctor;
8456         MonoObject *retval;
8457         void *params [2], *unboxed;
8458
8459         if (!klass)
8460                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8461         if (!ctor)
8462                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8463         
8464         params [0] = mono_type_get_object (mono_domain_get (), t);
8465         params [1] = val;
8466         retval = mono_object_new (mono_domain_get (), klass);
8467         unboxed = mono_object_unbox (retval);
8468         mono_runtime_invoke (ctor, unboxed, params, NULL);
8469
8470         return retval;
8471 }
8472
8473 static MonoObject*
8474 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8475 {
8476         static MonoClass *klass;
8477         static MonoMethod *ctor;
8478         MonoObject *retval;
8479         void *unboxed, *params [2];
8480
8481         if (!klass)
8482                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8483         if (!ctor)
8484                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8485
8486         params [0] = minfo;
8487         params [1] = typedarg;
8488         retval = mono_object_new (mono_domain_get (), klass);
8489         unboxed = mono_object_unbox (retval);
8490         mono_runtime_invoke (ctor, unboxed, params, NULL);
8491
8492         return retval;
8493 }
8494
8495 static gboolean
8496 type_is_reference (MonoType *type)
8497 {
8498         switch (type->type) {
8499         case MONO_TYPE_BOOLEAN:
8500         case MONO_TYPE_CHAR:
8501         case MONO_TYPE_U:
8502         case MONO_TYPE_I:
8503         case MONO_TYPE_U1:
8504         case MONO_TYPE_I1:
8505         case MONO_TYPE_U2:
8506         case MONO_TYPE_I2:
8507         case MONO_TYPE_U4:
8508         case MONO_TYPE_I4:
8509         case MONO_TYPE_U8:
8510         case MONO_TYPE_I8:
8511         case MONO_TYPE_R8:
8512         case MONO_TYPE_R4:
8513         case MONO_TYPE_VALUETYPE:
8514                 return FALSE;
8515         default:
8516                 return TRUE;
8517         }
8518 }
8519
8520 static void
8521 free_param_data (MonoMethodSignature *sig, void **params) {
8522         int i;
8523         for (i = 0; i < sig->param_count; ++i) {
8524                 if (!type_is_reference (sig->params [i]))
8525                         g_free (params [i]);
8526         }
8527 }
8528
8529 /*
8530  * Find the field index in the metadata FieldDef table.
8531  */
8532 static guint32
8533 find_field_index (MonoClass *klass, MonoClassField *field) {
8534         int i;
8535
8536         for (i = 0; i < klass->field.count; ++i) {
8537                 if (field == &klass->fields [i])
8538                         return klass->field.first + 1 + i;
8539         }
8540         return 0;
8541 }
8542
8543 /*
8544  * Find the property index in the metadata Property table.
8545  */
8546 static guint32
8547 find_property_index (MonoClass *klass, MonoProperty *property) {
8548         int i;
8549
8550         for (i = 0; i < klass->ext->property.count; ++i) {
8551                 if (property == &klass->ext->properties [i])
8552                         return klass->ext->property.first + 1 + i;
8553         }
8554         return 0;
8555 }
8556
8557 /*
8558  * Find the event index in the metadata Event table.
8559  */
8560 static guint32
8561 find_event_index (MonoClass *klass, MonoEvent *event) {
8562         int i;
8563
8564         for (i = 0; i < klass->ext->event.count; ++i) {
8565                 if (event == &klass->ext->events [i])
8566                         return klass->ext->event.first + 1 + i;
8567         }
8568         return 0;
8569 }
8570
8571 static MonoObject*
8572 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8573 {
8574         const char *p = (const char*)data;
8575         const char *named;
8576         guint32 i, j, num_named;
8577         MonoObject *attr;
8578         void *params_buf [32];
8579         void **params = NULL;
8580         MonoMethodSignature *sig;
8581         MonoObject *exc = NULL;
8582
8583         mono_error_init (error);
8584
8585         mono_class_init (method->klass);
8586
8587         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8588                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8589                 return NULL;
8590         }
8591
8592         if (len == 0) {
8593                 attr = mono_object_new (mono_domain_get (), method->klass);
8594                 mono_runtime_invoke (method, attr, NULL, NULL);
8595                 return attr;
8596         }
8597
8598         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8599                 return NULL;
8600
8601         /*g_print ("got attr %s\n", method->klass->name);*/
8602
8603         sig = mono_method_signature (method);
8604         if (sig->param_count < 32) {
8605                 params = params_buf;
8606                 memset (params, 0, sizeof (void*) * sig->param_count);
8607         } else {
8608                 /* Allocate using GC so it gets GC tracking */
8609                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8610         }
8611
8612         /* skip prolog */
8613         p += 2;
8614         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8615                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8616                 if (!mono_error_ok (error))
8617                         goto fail;
8618         }
8619
8620         named = p;
8621         attr = mono_object_new (mono_domain_get (), method->klass);
8622
8623         mono_runtime_invoke (method, attr, params, &exc);
8624         if (exc)
8625                 goto fail;
8626         num_named = read16 (named);
8627         named += 2;
8628         for (j = 0; j < num_named; j++) {
8629                 gint name_len;
8630                 char *name, named_type, data_type;
8631                 named_type = *named++;
8632                 data_type = *named++; /* type of data */
8633                 if (data_type == MONO_TYPE_SZARRAY)
8634                         data_type = *named++;
8635                 if (data_type == MONO_TYPE_ENUM) {
8636                         gint type_len;
8637                         char *type_name;
8638                         type_len = mono_metadata_decode_blob_size (named, &named);
8639                         type_name = g_malloc (type_len + 1);
8640                         memcpy (type_name, named, type_len);
8641                         type_name [type_len] = 0;
8642                         named += type_len;
8643                         /* FIXME: lookup the type and check type consistency */
8644                         g_free (type_name);
8645                 }
8646                 name_len = mono_metadata_decode_blob_size (named, &named);
8647                 name = g_malloc (name_len + 1);
8648                 memcpy (name, named, name_len);
8649                 name [name_len] = 0;
8650                 named += name_len;
8651                 if (named_type == 0x53) {
8652                         MonoClassField *field;
8653                         void *val;
8654
8655                         /* how this fail is a blackbox */
8656                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8657                         if (!field) {
8658                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8659                                 g_free (name);
8660                                 goto fail;
8661                         }
8662
8663                         val = load_cattr_value (image, field->type, named, &named, error);
8664                         if (!mono_error_ok (error)) {
8665                                 g_free (name);
8666                                 if (!type_is_reference (field->type))
8667                                         g_free (val);
8668                                 goto fail;
8669                         }
8670
8671                         mono_field_set_value (attr, field, val);
8672                         if (!type_is_reference (field->type))
8673                                 g_free (val);
8674                 } else if (named_type == 0x54) {
8675                         MonoProperty *prop;
8676                         void *pparams [1];
8677                         MonoType *prop_type;
8678
8679                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8680
8681                         if (!prop) {
8682                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8683                                 g_free (name);
8684                                 goto fail;
8685                         }
8686
8687                         if (!prop->set) {
8688                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8689                                 g_free (name);
8690                                 goto fail;
8691                         }
8692
8693                         /* can we have more that 1 arg in a custom attr named property? */
8694                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8695                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8696
8697                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8698                         if (!mono_error_ok (error)) {
8699                                 g_free (name);
8700                                 if (!type_is_reference (prop_type))
8701                                         g_free (pparams [0]);
8702                                 goto fail;
8703                         }
8704
8705
8706                         mono_property_set_value (prop, attr, pparams, NULL);
8707                         if (!type_is_reference (prop_type))
8708                                 g_free (pparams [0]);
8709                 }
8710                 g_free (name);
8711         }
8712
8713         free_param_data (method->signature, params);
8714         if (params != params_buf)
8715                 mono_gc_free_fixed (params);
8716
8717         return attr;
8718
8719 fail:
8720         free_param_data (method->signature, params);
8721         if (params != params_buf)
8722                 mono_gc_free_fixed (params);
8723         if (exc)
8724                 mono_raise_exception ((MonoException*)exc);
8725         return NULL;
8726 }
8727         
8728 /*
8729  * mono_reflection_create_custom_attr_data_args:
8730  *
8731  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8732  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8733  * NAMED_ARG_INFO will contain information about the named arguments.
8734  */
8735 void
8736 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)
8737 {
8738         MonoArray *typedargs, *namedargs;
8739         MonoClass *attrklass;
8740         MonoDomain *domain;
8741         const char *p = (const char*)data;
8742         const char *named;
8743         guint32 i, j, num_named;
8744         CattrNamedArg *arginfo = NULL;
8745
8746         *typed_args = NULL;
8747         *named_args = NULL;
8748         *named_arg_info = NULL;
8749
8750         mono_error_init (error);
8751
8752         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8753                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8754                 return;
8755         }
8756
8757         mono_class_init (method->klass);
8758         
8759         domain = mono_domain_get ();
8760
8761         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8762                 return;
8763
8764         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8765         
8766         /* skip prolog */
8767         p += 2;
8768         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8769                 MonoObject *obj;
8770                 void *val;
8771
8772                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8773                 if (!mono_error_ok (error)) {
8774                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8775                                 g_free (val);
8776                         return;
8777                 }
8778
8779                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8780                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8781                 mono_array_setref (typedargs, i, obj);
8782
8783                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8784                         g_free (val);
8785         }
8786
8787         named = p;
8788         num_named = read16 (named);
8789         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8790         named += 2;
8791         attrklass = method->klass;
8792
8793         arginfo = g_new0 (CattrNamedArg, num_named);
8794         *named_arg_info = arginfo;
8795
8796         for (j = 0; j < num_named; j++) {
8797                 gint name_len;
8798                 char *name, named_type, data_type;
8799                 named_type = *named++;
8800                 data_type = *named++; /* type of data */
8801                 if (data_type == MONO_TYPE_SZARRAY)
8802                         data_type = *named++;
8803                 if (data_type == MONO_TYPE_ENUM) {
8804                         gint type_len;
8805                         char *type_name;
8806                         type_len = mono_metadata_decode_blob_size (named, &named);
8807                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8808                                 goto fail;
8809
8810                         type_name = g_malloc (type_len + 1);
8811                         memcpy (type_name, named, type_len);
8812                         type_name [type_len] = 0;
8813                         named += type_len;
8814                         /* FIXME: lookup the type and check type consistency */
8815                         g_free (type_name);
8816                 }
8817                 name_len = mono_metadata_decode_blob_size (named, &named);
8818                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8819                         goto fail;
8820                 name = g_malloc (name_len + 1);
8821                 memcpy (name, named, name_len);
8822                 name [name_len] = 0;
8823                 named += name_len;
8824                 if (named_type == 0x53) {
8825                         MonoObject *obj;
8826                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8827                         void *val;
8828
8829                         if (!field) {
8830                                 g_free (name);
8831                                 goto fail;
8832                         }
8833
8834                         arginfo [j].type = field->type;
8835                         arginfo [j].field = field;
8836
8837                         val = load_cattr_value (image, field->type, named, &named, error);
8838                         if (!mono_error_ok (error)) {
8839                                 if (!type_is_reference (field->type))
8840                                         g_free (val);
8841                                 g_free (name);
8842                                 return;
8843                         }
8844
8845                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8846                         mono_array_setref (namedargs, j, obj);
8847                         if (!type_is_reference (field->type))
8848                                 g_free (val);
8849                 } else if (named_type == 0x54) {
8850                         MonoObject *obj;
8851                         MonoType *prop_type;
8852                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8853                         void *val;
8854
8855                         if (!prop || !prop->set) {
8856                                 g_free (name);
8857                                 goto fail;
8858                         }
8859
8860                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8861                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8862
8863                         arginfo [j].type = prop_type;
8864                         arginfo [j].prop = prop;
8865
8866                         val = load_cattr_value (image, prop_type, named, &named, error);
8867                         if (!mono_error_ok (error)) {
8868                                 if (!type_is_reference (prop_type))
8869                                         g_free (val);
8870                                 g_free (name);
8871                                 return;
8872                         }
8873
8874                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8875                         mono_array_setref (namedargs, j, obj);
8876                         if (!type_is_reference (prop_type))
8877                                 g_free (val);
8878                 }
8879                 g_free (name);
8880         }
8881
8882         *typed_args = typedargs;
8883         *named_args = namedargs;
8884         return;
8885 fail:
8886         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8887         g_free (arginfo);
8888         *named_arg_info = NULL;
8889 }
8890
8891 void
8892 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8893 {
8894         MonoDomain *domain;
8895         MonoArray *typedargs, *namedargs;
8896         MonoImage *image;
8897         MonoMethod *method;
8898         CattrNamedArg *arginfo = NULL;
8899         MonoError error;
8900         int i;
8901
8902         *ctor_args = NULL;
8903         *named_args = NULL;
8904
8905         if (len == 0)
8906                 return;
8907
8908         image = assembly->assembly->image;
8909         method = ref_method->method;
8910         domain = mono_object_domain (ref_method);
8911
8912         if (!mono_class_init (method->klass))
8913                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8914
8915         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8916         if (!mono_error_ok (&error))
8917                 mono_error_raise_exception (&error);
8918         if (mono_loader_get_last_error ())
8919                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8920
8921         if (!typedargs || !namedargs) {
8922                 g_free (arginfo);
8923                 return;
8924         }
8925
8926         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8927                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8928                 MonoObject *typedarg;
8929
8930                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8931                 mono_array_setref (typedargs, i, typedarg);
8932         }
8933
8934         for (i = 0; i < mono_array_length (namedargs); ++i) {
8935                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8936                 MonoObject *typedarg, *namedarg, *minfo;
8937
8938                 if (arginfo [i].prop)
8939                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8940                 else
8941                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8942
8943                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8944                 namedarg = create_cattr_named_arg (minfo, typedarg);
8945
8946                 mono_array_setref (namedargs, i, namedarg);
8947         }
8948
8949         *ctor_args = typedargs;
8950         *named_args = namedargs;
8951         g_free (arginfo);
8952 }
8953
8954 static MonoObject*
8955 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8956 {
8957         static MonoMethod *ctor;
8958         MonoDomain *domain;
8959         MonoObject *attr;
8960         void *params [4];
8961
8962         g_assert (image->assembly);
8963
8964         if (!ctor)
8965                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8966
8967         domain = mono_domain_get ();
8968         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8969         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8970         params [1] = mono_assembly_get_object (domain, image->assembly);
8971         params [2] = (gpointer)&cattr->data;
8972         params [3] = &cattr->data_size;
8973         mono_runtime_invoke (ctor, attr, params, NULL);
8974         return attr;
8975 }
8976
8977 static MonoArray*
8978 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8979 {
8980         MonoArray *result;
8981         MonoObject *attr;
8982         int i, n;
8983
8984         mono_error_init (error);
8985
8986         n = 0;
8987         for (i = 0; i < cinfo->num_attrs; ++i) {
8988                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8989                         n ++;
8990         }
8991
8992         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8993         n = 0;
8994         for (i = 0; i < cinfo->num_attrs; ++i) {
8995                 if (!cinfo->attrs [i].ctor)
8996                         /* The cattr type is not finished yet */
8997                         /* We should include the type name but cinfo doesn't contain it */
8998                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8999                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9000                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9001                         if (!mono_error_ok (error))
9002                                 return result;
9003                         mono_array_setref (result, n, attr);
9004                         n ++;
9005                 }
9006         }
9007         return result;
9008 }
9009
9010 MonoArray*
9011 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9012 {
9013         MonoError error;
9014         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9015         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9016
9017         return result;
9018 }
9019
9020 static MonoArray*
9021 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9022 {
9023         MonoArray *result;
9024         MonoObject *attr;
9025         int i;
9026         
9027         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9028         for (i = 0; i < cinfo->num_attrs; ++i) {
9029                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9030                 mono_array_setref (result, i, attr);
9031         }
9032         return result;
9033 }
9034
9035 /**
9036  * mono_custom_attrs_from_index:
9037  *
9038  * Returns: NULL if no attributes are found or if a loading error occurs.
9039  */
9040 MonoCustomAttrInfo*
9041 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9042 {
9043         guint32 mtoken, i, len;
9044         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9045         MonoTableInfo *ca;
9046         MonoCustomAttrInfo *ainfo;
9047         GList *tmp, *list = NULL;
9048         const char *data;
9049         MonoCustomAttrEntry* attr;
9050
9051         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9052
9053         i = mono_metadata_custom_attrs_from_index (image, idx);
9054         if (!i)
9055                 return NULL;
9056         i --;
9057         while (i < ca->rows) {
9058                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9059                         break;
9060                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9061                 ++i;
9062         }
9063         len = g_list_length (list);
9064         if (!len)
9065                 return NULL;
9066         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9067         ainfo->num_attrs = len;
9068         ainfo->image = image;
9069         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9070                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9071                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9072                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9073                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9074                         mtoken |= MONO_TOKEN_METHOD_DEF;
9075                         break;
9076                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9077                         mtoken |= MONO_TOKEN_MEMBER_REF;
9078                         break;
9079                 default:
9080                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9081                         break;
9082                 }
9083                 attr = &ainfo->attrs [i - 1];
9084                 attr->ctor = mono_get_method (image, mtoken, NULL);
9085                 if (!attr->ctor) {
9086                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
9087                         g_list_free (list);
9088                         g_free (ainfo);
9089                         return NULL;
9090                 }
9091
9092                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9093                         /*FIXME raising an exception here doesn't make any sense*/
9094                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9095                         g_list_free (list);
9096                         g_free (ainfo);
9097                         return NULL;
9098                 }
9099                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9100                 attr->data_size = mono_metadata_decode_value (data, &data);
9101                 attr->data = (guchar*)data;
9102         }
9103         g_list_free (list);
9104
9105         return ainfo;
9106 }
9107
9108 MonoCustomAttrInfo*
9109 mono_custom_attrs_from_method (MonoMethod *method)
9110 {
9111         guint32 idx;
9112
9113         /*
9114          * An instantiated method has the same cattrs as the generic method definition.
9115          *
9116          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9117          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9118          */
9119         if (method->is_inflated)
9120                 method = ((MonoMethodInflated *) method)->declaring;
9121         
9122         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9123                 return lookup_custom_attr (method->klass->image, method);
9124
9125         if (!method->token)
9126                 /* Synthetic methods */
9127                 return NULL;
9128
9129         idx = mono_method_get_index (method);
9130         idx <<= MONO_CUSTOM_ATTR_BITS;
9131         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9132         return mono_custom_attrs_from_index (method->klass->image, idx);
9133 }
9134
9135 MonoCustomAttrInfo*
9136 mono_custom_attrs_from_class (MonoClass *klass)
9137 {
9138         guint32 idx;
9139
9140         if (klass->generic_class)
9141                 klass = klass->generic_class->container_class;
9142
9143         if (image_is_dynamic (klass->image))
9144                 return lookup_custom_attr (klass->image, klass);
9145
9146         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9147                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9148                 idx <<= MONO_CUSTOM_ATTR_BITS;
9149                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9150         } else {
9151                 idx = mono_metadata_token_index (klass->type_token);
9152                 idx <<= MONO_CUSTOM_ATTR_BITS;
9153                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9154         }
9155         return mono_custom_attrs_from_index (klass->image, idx);
9156 }
9157
9158 MonoCustomAttrInfo*
9159 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9160 {
9161         guint32 idx;
9162         
9163         if (image_is_dynamic (assembly->image))
9164                 return lookup_custom_attr (assembly->image, assembly);
9165         idx = 1; /* there is only one assembly */
9166         idx <<= MONO_CUSTOM_ATTR_BITS;
9167         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9168         return mono_custom_attrs_from_index (assembly->image, idx);
9169 }
9170
9171 static MonoCustomAttrInfo*
9172 mono_custom_attrs_from_module (MonoImage *image)
9173 {
9174         guint32 idx;
9175         
9176         if (image_is_dynamic (image))
9177                 return lookup_custom_attr (image, image);
9178         idx = 1; /* there is only one module */
9179         idx <<= MONO_CUSTOM_ATTR_BITS;
9180         idx |= MONO_CUSTOM_ATTR_MODULE;
9181         return mono_custom_attrs_from_index (image, idx);
9182 }
9183
9184 MonoCustomAttrInfo*
9185 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9186 {
9187         guint32 idx;
9188         
9189         if (image_is_dynamic (klass->image)) {
9190                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9191                 return lookup_custom_attr (klass->image, property);
9192         }
9193         idx = find_property_index (klass, property);
9194         idx <<= MONO_CUSTOM_ATTR_BITS;
9195         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9196         return mono_custom_attrs_from_index (klass->image, idx);
9197 }
9198
9199 MonoCustomAttrInfo*
9200 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9201 {
9202         guint32 idx;
9203         
9204         if (image_is_dynamic (klass->image)) {
9205                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9206                 return lookup_custom_attr (klass->image, event);
9207         }
9208         idx = find_event_index (klass, event);
9209         idx <<= MONO_CUSTOM_ATTR_BITS;
9210         idx |= MONO_CUSTOM_ATTR_EVENT;
9211         return mono_custom_attrs_from_index (klass->image, idx);
9212 }
9213
9214 MonoCustomAttrInfo*
9215 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9216 {
9217         guint32 idx;
9218         if (image_is_dynamic (klass->image)) {
9219                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9220                 return lookup_custom_attr (klass->image, field);
9221         }
9222         idx = find_field_index (klass, field);
9223         idx <<= MONO_CUSTOM_ATTR_BITS;
9224         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9225         return mono_custom_attrs_from_index (klass->image, idx);
9226 }
9227
9228 /**
9229  * mono_custom_attrs_from_param:
9230  * @method: handle to the method that we want to retrieve custom parameter information from
9231  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9232  *
9233  * The result must be released with mono_custom_attrs_free().
9234  *
9235  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9236  */
9237 MonoCustomAttrInfo*
9238 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9239 {
9240         MonoTableInfo *ca;
9241         guint32 i, idx, method_index;
9242         guint32 param_list, param_last, param_pos, found;
9243         MonoImage *image;
9244         MonoReflectionMethodAux *aux;
9245
9246         /*
9247          * An instantiated method has the same cattrs as the generic method definition.
9248          *
9249          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9250          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9251          */
9252         if (method->is_inflated)
9253                 method = ((MonoMethodInflated *) method)->declaring;
9254
9255         if (image_is_dynamic (method->klass->image)) {
9256                 MonoCustomAttrInfo *res, *ainfo;
9257                 int size;
9258
9259                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9260                 if (!aux || !aux->param_cattr)
9261                         return NULL;
9262
9263                 /* Need to copy since it will be freed later */
9264                 ainfo = aux->param_cattr [param];
9265                 if (!ainfo)
9266                         return NULL;
9267                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9268                 res = g_malloc0 (size);
9269                 memcpy (res, ainfo, size);
9270                 return res;
9271         }
9272
9273         image = method->klass->image;
9274         method_index = mono_method_get_index (method);
9275         if (!method_index)
9276                 return NULL;
9277         ca = &image->tables [MONO_TABLE_METHOD];
9278
9279         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9280         if (method_index == ca->rows) {
9281                 ca = &image->tables [MONO_TABLE_PARAM];
9282                 param_last = ca->rows + 1;
9283         } else {
9284                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9285                 ca = &image->tables [MONO_TABLE_PARAM];
9286         }
9287         found = FALSE;
9288         for (i = param_list; i < param_last; ++i) {
9289                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9290                 if (param_pos == param) {
9291                         found = TRUE;
9292                         break;
9293                 }
9294         }
9295         if (!found)
9296                 return NULL;
9297         idx = i;
9298         idx <<= MONO_CUSTOM_ATTR_BITS;
9299         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9300         return mono_custom_attrs_from_index (image, idx);
9301 }
9302
9303 gboolean
9304 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9305 {
9306         int i;
9307         MonoClass *klass;
9308         for (i = 0; i < ainfo->num_attrs; ++i) {
9309                 klass = ainfo->attrs [i].ctor->klass;
9310                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9311                         return TRUE;
9312         }
9313         return FALSE;
9314 }
9315
9316 MonoObject*
9317 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9318 {
9319         MonoError error;
9320         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9321         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9322         return res;
9323 }
9324
9325 MonoObject*
9326 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9327 {
9328         int i, attr_index;
9329         MonoClass *klass;
9330         MonoArray *attrs;
9331
9332         mono_error_init (error);
9333
9334         attr_index = -1;
9335         for (i = 0; i < ainfo->num_attrs; ++i) {
9336                 klass = ainfo->attrs [i].ctor->klass;
9337                 if (mono_class_has_parent (klass, attr_klass)) {
9338                         attr_index = i;
9339                         break;
9340                 }
9341         }
9342         if (attr_index == -1)
9343                 return NULL;
9344
9345         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9346         if (!mono_error_ok (error))
9347                 return NULL;
9348         return mono_array_get (attrs, MonoObject*, attr_index);
9349 }
9350
9351 /*
9352  * mono_reflection_get_custom_attrs_info:
9353  * @obj: a reflection object handle
9354  *
9355  * Return the custom attribute info for attributes defined for the
9356  * reflection handle @obj. The objects.
9357  *
9358  * FIXME this function leaks like a sieve for SRE objects.
9359  */
9360 MonoCustomAttrInfo*
9361 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9362 {
9363         MonoClass *klass;
9364         MonoCustomAttrInfo *cinfo = NULL;
9365         
9366         klass = obj->vtable->klass;
9367         if (klass == mono_defaults.monotype_class) {
9368                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9369                 klass = mono_class_from_mono_type (type);
9370                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9371                 cinfo = mono_custom_attrs_from_class (klass);
9372         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9373                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9374                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9375         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9376                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9377                 cinfo = mono_custom_attrs_from_module (module->image);
9378         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9379                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9380                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9381         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9382                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9383                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9384         } else if (strcmp ("MonoField", klass->name) == 0) {
9385                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9386                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9387         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9388                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9389                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9390         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9391                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9392                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9393         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9394                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9395                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9396                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9397                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9398                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9399                 } else if (is_sr_mono_property (member_class)) {
9400                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9401                         MonoMethod *method;
9402                         if (!(method = prop->property->get))
9403                                 method = prop->property->set;
9404                         g_assert (method);
9405
9406                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9407                 } 
9408 #ifndef DISABLE_REFLECTION_EMIT
9409                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9410                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9411                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9412                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9413                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9414                         MonoMethod *method = NULL;
9415                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9416                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9417                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9418                                 method = ((MonoReflectionMethod *)c->cb)->method;
9419                         else
9420                                 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));
9421
9422                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9423                 } 
9424 #endif
9425                 else {
9426                         char *type_name = mono_type_get_full_name (member_class);
9427                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9428                         MonoException *ex = mono_get_exception_not_supported  (msg);
9429                         g_free (type_name);
9430                         g_free (msg);
9431                         mono_raise_exception (ex);
9432                 }
9433         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9434                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9435                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9436         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9437                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9438                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9439         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9440                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9441                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9442         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9443                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9444                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9445         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9446                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9447                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9448         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9449                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9450                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9451         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9452                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9453                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9454         } else { /* handle other types here... */
9455                 g_error ("get custom attrs not yet supported for %s", klass->name);
9456         }
9457
9458         return cinfo;
9459 }
9460
9461 /*
9462  * mono_reflection_get_custom_attrs_by_type:
9463  * @obj: a reflection object handle
9464  *
9465  * Return an array with all the custom attributes defined of the
9466  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9467  * of that type are returned. The objects are fully build. Return NULL if a loading error
9468  * occurs.
9469  */
9470 MonoArray*
9471 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9472 {
9473         MonoArray *result;
9474         MonoCustomAttrInfo *cinfo;
9475
9476         mono_error_init (error);
9477
9478         cinfo = mono_reflection_get_custom_attrs_info (obj);
9479         if (cinfo) {
9480                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9481                 if (!cinfo->cached)
9482                         mono_custom_attrs_free (cinfo);
9483         } else {
9484                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9485                 if (mono_loader_get_last_error ())
9486                         return NULL;
9487                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9488         }
9489
9490         return result;
9491 }
9492
9493 /*
9494  * mono_reflection_get_custom_attrs:
9495  * @obj: a reflection object handle
9496  *
9497  * Return an array with all the custom attributes defined of the
9498  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9499  * occurs.
9500  */
9501 MonoArray*
9502 mono_reflection_get_custom_attrs (MonoObject *obj)
9503 {
9504         MonoError error;
9505
9506         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9507 }
9508
9509 /*
9510  * mono_reflection_get_custom_attrs_data:
9511  * @obj: a reflection obj handle
9512  *
9513  * Returns an array of System.Reflection.CustomAttributeData,
9514  * which include information about attributes reflected on
9515  * types loaded using the Reflection Only methods
9516  */
9517 MonoArray*
9518 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9519 {
9520         MonoArray *result;
9521         MonoCustomAttrInfo *cinfo;
9522
9523         cinfo = mono_reflection_get_custom_attrs_info (obj);
9524         if (cinfo) {
9525                 result = mono_custom_attrs_data_construct (cinfo);
9526                 if (!cinfo->cached)
9527                         mono_custom_attrs_free (cinfo);
9528         } else
9529                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9530
9531         return result;
9532 }
9533
9534 static MonoReflectionType*
9535 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9536 {
9537         static MonoMethod *method_get_underlying_system_type = NULL;
9538         MonoMethod *usertype_method;
9539
9540         if (!method_get_underlying_system_type)
9541                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9542         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9543         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9544 }
9545
9546
9547 static gboolean
9548 is_corlib_type (MonoClass *klass)
9549 {
9550         return klass->image == mono_defaults.corlib;
9551 }
9552
9553 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9554         static MonoClass *cached_class; \
9555         if (cached_class) \
9556                 return cached_class == _class; \
9557         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9558                 cached_class = _class; \
9559                 return TRUE; \
9560         } \
9561         return FALSE; \
9562 } while (0) \
9563
9564
9565 #ifndef DISABLE_REFLECTION_EMIT
9566 static gboolean
9567 is_sre_array (MonoClass *klass)
9568 {
9569         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9570 }
9571
9572 static gboolean
9573 is_sre_byref (MonoClass *klass)
9574 {
9575         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9576 }
9577
9578 static gboolean
9579 is_sre_pointer (MonoClass *klass)
9580 {
9581         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9582 }
9583
9584 static gboolean
9585 is_sre_generic_instance (MonoClass *klass)
9586 {
9587         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9588 }
9589
9590 static gboolean
9591 is_sre_type_builder (MonoClass *klass)
9592 {
9593         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9594 }
9595
9596 static gboolean
9597 is_sre_method_builder (MonoClass *klass)
9598 {
9599         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9600 }
9601
9602 static gboolean
9603 is_sre_ctor_builder (MonoClass *klass)
9604 {
9605         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9606 }
9607
9608 static gboolean
9609 is_sre_field_builder (MonoClass *klass)
9610 {
9611         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9612 }
9613
9614 static gboolean
9615 is_sre_method_on_tb_inst (MonoClass *klass)
9616 {
9617         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9618 }
9619
9620 static gboolean
9621 is_sre_ctor_on_tb_inst (MonoClass *klass)
9622 {
9623         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9624 }
9625
9626 MonoType*
9627 mono_reflection_type_get_handle (MonoReflectionType* ref)
9628 {
9629         MonoClass *klass;
9630         if (!ref)
9631                 return NULL;
9632         if (ref->type)
9633                 return ref->type;
9634
9635         if (is_usertype (ref)) {
9636                 ref = mono_reflection_type_get_underlying_system_type (ref);
9637                 if (ref == NULL || is_usertype (ref))
9638                         return NULL;
9639                 if (ref->type)
9640                         return ref->type;
9641         }
9642
9643         klass = mono_object_class (ref);
9644
9645         if (is_sre_array (klass)) {
9646                 MonoType *res;
9647                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9648                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9649                 g_assert (base);
9650                 if (sre_array->rank == 0) //single dimentional array
9651                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9652                 else
9653                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9654                 sre_array->type.type = res;
9655                 return res;
9656         } else if (is_sre_byref (klass)) {
9657                 MonoType *res;
9658                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9659                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9660                 g_assert (base);
9661                 res = &mono_class_from_mono_type (base)->this_arg;
9662                 sre_byref->type.type = res;
9663                 return res;
9664         } else if (is_sre_pointer (klass)) {
9665                 MonoType *res;
9666                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9667                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9668                 g_assert (base);
9669                 res = &mono_ptr_class_get (base)->byval_arg;
9670                 sre_pointer->type.type = res;
9671                 return res;
9672         } else if (is_sre_generic_instance (klass)) {
9673                 MonoType *res, **types;
9674                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9675                 int i, count;
9676
9677                 count = mono_array_length (gclass->type_arguments);
9678                 types = g_new0 (MonoType*, count);
9679                 for (i = 0; i < count; ++i) {
9680                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9681                         types [i] = mono_reflection_type_get_handle (t);
9682                         if (!types[i]) {
9683                                 g_free (types);
9684                                 return NULL;
9685                         }
9686                 }
9687
9688                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9689                 g_free (types);
9690                 g_assert (res);
9691                 gclass->type.type = res;
9692                 return res;
9693         }
9694
9695         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9696         return NULL;
9697 }
9698
9699
9700
9701 void
9702 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9703 {
9704         mono_reflection_type_get_handle (type);
9705 }
9706
9707 void
9708 mono_reflection_register_with_runtime (MonoReflectionType *type)
9709 {
9710         MonoType *res = mono_reflection_type_get_handle (type);
9711         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9712         MonoClass *klass;
9713
9714         if (!res)
9715                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9716
9717         klass = mono_class_from_mono_type (res);
9718
9719         mono_loader_lock (); /*same locking as mono_type_get_object*/
9720         mono_domain_lock (domain);
9721
9722         if (!image_is_dynamic (klass->image)) {
9723                 mono_class_setup_supertypes (klass);
9724         } else {
9725                 if (!domain->type_hash)
9726                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9727                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9728                 mono_g_hash_table_insert (domain->type_hash, res, type);
9729         }
9730         mono_domain_unlock (domain);
9731         mono_loader_unlock ();
9732 }
9733
9734 /**
9735  * LOCKING: Assumes the loader lock is held.
9736  */
9737 static MonoMethodSignature*
9738 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9739         MonoMethodSignature *sig;
9740         int count, i;
9741
9742         count = parameters? mono_array_length (parameters): 0;
9743
9744         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9745         sig->param_count = count;
9746         sig->sentinelpos = -1; /* FIXME */
9747         for (i = 0; i < count; ++i)
9748                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9749         return sig;
9750 }
9751
9752 /**
9753  * LOCKING: Assumes the loader lock is held.
9754  */
9755 static MonoMethodSignature*
9756 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9757         MonoMethodSignature *sig;
9758
9759         sig = parameters_to_signature (image, ctor->parameters);
9760         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9761         sig->ret = &mono_defaults.void_class->byval_arg;
9762         return sig;
9763 }
9764
9765 /**
9766  * LOCKING: Assumes the loader lock is held.
9767  */
9768 static MonoMethodSignature*
9769 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9770         MonoMethodSignature *sig;
9771
9772         sig = parameters_to_signature (image, method->parameters);
9773         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9774         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9775         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9776         return sig;
9777 }
9778
9779 static MonoMethodSignature*
9780 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9781         MonoMethodSignature *sig;
9782
9783         sig = parameters_to_signature (NULL, method->parameters);
9784         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9785         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9786         sig->generic_param_count = 0;
9787         return sig;
9788 }
9789
9790 static void
9791 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9792 {
9793         MonoClass *klass = mono_object_class (prop);
9794         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9795                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9796                 *name = mono_string_to_utf8 (pb->name);
9797                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9798         } else {
9799                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9800                 *name = g_strdup (p->property->name);
9801                 if (p->property->get)
9802                         *type = mono_method_signature (p->property->get)->ret;
9803                 else
9804                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9805         }
9806 }
9807
9808 static void
9809 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9810 {
9811         MonoClass *klass = mono_object_class (field);
9812         if (strcmp (klass->name, "FieldBuilder") == 0) {
9813                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9814                 *name = mono_string_to_utf8 (fb->name);
9815                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9816         } else {
9817                 MonoReflectionField *f = (MonoReflectionField *)field;
9818                 *name = g_strdup (mono_field_get_name (f->field));
9819                 *type = f->field->type;
9820         }
9821 }
9822
9823 #else /* DISABLE_REFLECTION_EMIT */
9824
9825 void
9826 mono_reflection_register_with_runtime (MonoReflectionType *type)
9827 {
9828         /* This is empty */
9829 }
9830
9831 static gboolean
9832 is_sre_type_builder (MonoClass *klass)
9833 {
9834         return FALSE;
9835 }
9836
9837 static gboolean
9838 is_sre_generic_instance (MonoClass *klass)
9839 {
9840         return FALSE;
9841 }
9842
9843 static void
9844 init_type_builder_generics (MonoObject *type)
9845 {
9846 }
9847
9848 #endif /* !DISABLE_REFLECTION_EMIT */
9849
9850
9851 static gboolean
9852 is_sr_mono_field (MonoClass *klass)
9853 {
9854         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9855 }
9856
9857 static gboolean
9858 is_sr_mono_property (MonoClass *klass)
9859 {
9860         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9861 }
9862
9863 static gboolean
9864 is_sr_mono_method (MonoClass *klass)
9865 {
9866         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9867 }
9868
9869 static gboolean
9870 is_sr_mono_cmethod (MonoClass *klass)
9871 {
9872         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9873 }
9874
9875 static gboolean
9876 is_sr_mono_generic_method (MonoClass *klass)
9877 {
9878         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9879 }
9880
9881 static gboolean
9882 is_sr_mono_generic_cmethod (MonoClass *klass)
9883 {
9884         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9885 }
9886
9887 gboolean
9888 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9889 {
9890         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9891 }
9892
9893 static gboolean
9894 is_usertype (MonoReflectionType *ref)
9895 {
9896         MonoClass *klass = mono_object_class (ref);
9897         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9898 }
9899
9900 static MonoReflectionType*
9901 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9902 {
9903         if (!type || type->type)
9904                 return type;
9905
9906         if (is_usertype (type)) {
9907                 type = mono_reflection_type_get_underlying_system_type (type);
9908                 if (is_usertype (type))
9909                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9910         }
9911
9912         return type;
9913 }
9914 /*
9915  * Encode a value in a custom attribute stream of bytes.
9916  * The value to encode is either supplied as an object in argument val
9917  * (valuetypes are boxed), or as a pointer to the data in the
9918  * argument argval.
9919  * @type represents the type of the value
9920  * @buffer is the start of the buffer
9921  * @p the current position in the buffer
9922  * @buflen contains the size of the buffer and is used to return the new buffer size
9923  * if this needs to be realloced.
9924  * @retbuffer and @retp return the start and the position of the buffer
9925  */
9926 static void
9927 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9928 {
9929         MonoTypeEnum simple_type;
9930         
9931         if ((p-buffer) + 10 >= *buflen) {
9932                 char *newbuf;
9933                 *buflen *= 2;
9934                 newbuf = g_realloc (buffer, *buflen);
9935                 p = newbuf + (p-buffer);
9936                 buffer = newbuf;
9937         }
9938         if (!argval)
9939                 argval = ((char*)arg + sizeof (MonoObject));
9940         simple_type = type->type;
9941 handle_enum:
9942         switch (simple_type) {
9943         case MONO_TYPE_BOOLEAN:
9944         case MONO_TYPE_U1:
9945         case MONO_TYPE_I1:
9946                 *p++ = *argval;
9947                 break;
9948         case MONO_TYPE_CHAR:
9949         case MONO_TYPE_U2:
9950         case MONO_TYPE_I2:
9951                 swap_with_size (p, argval, 2, 1);
9952                 p += 2;
9953                 break;
9954         case MONO_TYPE_U4:
9955         case MONO_TYPE_I4:
9956         case MONO_TYPE_R4:
9957                 swap_with_size (p, argval, 4, 1);
9958                 p += 4;
9959                 break;
9960         case MONO_TYPE_R8:
9961                 swap_with_size (p, argval, 8, 1);
9962                 p += 8;
9963                 break;
9964         case MONO_TYPE_U8:
9965         case MONO_TYPE_I8:
9966                 swap_with_size (p, argval, 8, 1);
9967                 p += 8;
9968                 break;
9969         case MONO_TYPE_VALUETYPE:
9970                 if (type->data.klass->enumtype) {
9971                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9972                         goto handle_enum;
9973                 } else {
9974                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9975                 }
9976                 break;
9977         case MONO_TYPE_STRING: {
9978                 char *str;
9979                 guint32 slen;
9980                 if (!arg) {
9981                         *p++ = 0xFF;
9982                         break;
9983                 }
9984                 str = mono_string_to_utf8 ((MonoString*)arg);
9985                 slen = strlen (str);
9986                 if ((p-buffer) + 10 + slen >= *buflen) {
9987                         char *newbuf;
9988                         *buflen *= 2;
9989                         *buflen += slen;
9990                         newbuf = g_realloc (buffer, *buflen);
9991                         p = newbuf + (p-buffer);
9992                         buffer = newbuf;
9993                 }
9994                 mono_metadata_encode_value (slen, p, &p);
9995                 memcpy (p, str, slen);
9996                 p += slen;
9997                 g_free (str);
9998                 break;
9999         }
10000         case MONO_TYPE_CLASS: {
10001                 char *str;
10002                 guint32 slen;
10003                 if (!arg) {
10004                         *p++ = 0xFF;
10005                         break;
10006                 }
10007 handle_type:
10008                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10009                 slen = strlen (str);
10010                 if ((p-buffer) + 10 + slen >= *buflen) {
10011                         char *newbuf;
10012                         *buflen *= 2;
10013                         *buflen += slen;
10014                         newbuf = g_realloc (buffer, *buflen);
10015                         p = newbuf + (p-buffer);
10016                         buffer = newbuf;
10017                 }
10018                 mono_metadata_encode_value (slen, p, &p);
10019                 memcpy (p, str, slen);
10020                 p += slen;
10021                 g_free (str);
10022                 break;
10023         }
10024         case MONO_TYPE_SZARRAY: {
10025                 int len, i;
10026                 MonoClass *eclass, *arg_eclass;
10027
10028                 if (!arg) {
10029                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10030                         break;
10031                 }
10032                 len = mono_array_length ((MonoArray*)arg);
10033                 *p++ = len & 0xff;
10034                 *p++ = (len >> 8) & 0xff;
10035                 *p++ = (len >> 16) & 0xff;
10036                 *p++ = (len >> 24) & 0xff;
10037                 *retp = p;
10038                 *retbuffer = buffer;
10039                 eclass = type->data.klass;
10040                 arg_eclass = mono_object_class (arg)->element_class;
10041
10042                 if (!eclass) {
10043                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10044                         eclass = mono_defaults.object_class;
10045                 }
10046                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10047                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10048                         int elsize = mono_class_array_element_size (arg_eclass);
10049                         for (i = 0; i < len; ++i) {
10050                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10051                                 elptr += elsize;
10052                         }
10053                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10054                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10055                         int elsize = mono_class_array_element_size (eclass);
10056                         for (i = 0; i < len; ++i) {
10057                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10058                                 elptr += elsize;
10059                         }
10060                 } else {
10061                         for (i = 0; i < len; ++i) {
10062                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10063                         }
10064                 }
10065                 break;
10066         }
10067         case MONO_TYPE_OBJECT: {
10068                 MonoClass *klass;
10069                 char *str;
10070                 guint32 slen;
10071
10072                 /*
10073                  * The parameter type is 'object' but the type of the actual
10074                  * argument is not. So we have to add type information to the blob
10075                  * too. This is completely undocumented in the spec.
10076                  */
10077
10078                 if (arg == NULL) {
10079                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10080                         *p++ = 0xFF;
10081                         break;
10082                 }
10083                 
10084                 klass = mono_object_class (arg);
10085
10086                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10087                         *p++ = 0x50;
10088                         goto handle_type;
10089                 } else if (klass->enumtype) {
10090                         *p++ = 0x55;
10091                 } else if (klass == mono_defaults.string_class) {
10092                         simple_type = MONO_TYPE_STRING;
10093                         *p++ = 0x0E;
10094                         goto handle_enum;
10095                 } else if (klass->rank == 1) {
10096                         *p++ = 0x1D;
10097                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10098                                 /* See Partition II, Appendix B3 */
10099                                 *p++ = 0x51;
10100                         else
10101                                 *p++ = klass->element_class->byval_arg.type;
10102                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10103                         break;
10104                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10105                         *p++ = simple_type = klass->byval_arg.type;
10106                         goto handle_enum;
10107                 } else {
10108                         g_error ("unhandled type in custom attr");
10109                 }
10110                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10111                 slen = strlen (str);
10112                 if ((p-buffer) + 10 + slen >= *buflen) {
10113                         char *newbuf;
10114                         *buflen *= 2;
10115                         *buflen += slen;
10116                         newbuf = g_realloc (buffer, *buflen);
10117                         p = newbuf + (p-buffer);
10118                         buffer = newbuf;
10119                 }
10120                 mono_metadata_encode_value (slen, p, &p);
10121                 memcpy (p, str, slen);
10122                 p += slen;
10123                 g_free (str);
10124                 simple_type = mono_class_enum_basetype (klass)->type;
10125                 goto handle_enum;
10126         }
10127         default:
10128                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10129         }
10130         *retp = p;
10131         *retbuffer = buffer;
10132 }
10133
10134 static void
10135 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10136 {
10137         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10138                 char *str = type_get_qualified_name (type, NULL);
10139                 int slen = strlen (str);
10140
10141                 *p++ = 0x55;
10142                 /*
10143                  * This seems to be optional...
10144                  * *p++ = 0x80;
10145                  */
10146                 mono_metadata_encode_value (slen, p, &p);
10147                 memcpy (p, str, slen);
10148                 p += slen;
10149                 g_free (str);
10150         } else if (type->type == MONO_TYPE_OBJECT) {
10151                 *p++ = 0x51;
10152         } else if (type->type == MONO_TYPE_CLASS) {
10153                 /* it should be a type: encode_cattr_value () has the check */
10154                 *p++ = 0x50;
10155         } else {
10156                 mono_metadata_encode_value (type->type, p, &p);
10157                 if (type->type == MONO_TYPE_SZARRAY)
10158                         /* See the examples in Partition VI, Annex B */
10159                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10160         }
10161
10162         *retp = p;
10163 }
10164
10165 #ifndef DISABLE_REFLECTION_EMIT
10166 static void
10167 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10168 {
10169         int len;
10170         /* Preallocate a large enough buffer */
10171         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10172                 char *str = type_get_qualified_name (type, NULL);
10173                 len = strlen (str);
10174                 g_free (str);
10175         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10176                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10177                 len = strlen (str);
10178                 g_free (str);
10179         } else {
10180                 len = 0;
10181         }
10182         len += strlen (name);
10183
10184         if ((p-buffer) + 20 + len >= *buflen) {
10185                 char *newbuf;
10186                 *buflen *= 2;
10187                 *buflen += len;
10188                 newbuf = g_realloc (buffer, *buflen);
10189                 p = newbuf + (p-buffer);
10190                 buffer = newbuf;
10191         }
10192
10193         encode_field_or_prop_type (type, p, &p);
10194
10195         len = strlen (name);
10196         mono_metadata_encode_value (len, p, &p);
10197         memcpy (p, name, len);
10198         p += len;
10199         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10200         *retp = p;
10201         *retbuffer = buffer;
10202 }
10203
10204 /*
10205  * mono_reflection_get_custom_attrs_blob:
10206  * @ctor: custom attribute constructor
10207  * @ctorArgs: arguments o the constructor
10208  * @properties:
10209  * @propValues:
10210  * @fields:
10211  * @fieldValues:
10212  * 
10213  * Creates the blob of data that needs to be saved in the metadata and that represents
10214  * the custom attributed described by @ctor, @ctorArgs etc.
10215  * Returns: a Byte array representing the blob of data.
10216  */
10217 MonoArray*
10218 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10219 {
10220         MonoArray *result;
10221         MonoMethodSignature *sig;
10222         MonoObject *arg;
10223         char *buffer, *p;
10224         guint32 buflen, i;
10225
10226         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10227                 /* sig is freed later so allocate it in the heap */
10228                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10229         } else {
10230                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10231         }
10232
10233         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10234         buflen = 256;
10235         p = buffer = g_malloc (buflen);
10236         /* write the prolog */
10237         *p++ = 1;
10238         *p++ = 0;
10239         for (i = 0; i < sig->param_count; ++i) {
10240                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10241                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10242         }
10243         i = 0;
10244         if (properties)
10245                 i += mono_array_length (properties);
10246         if (fields)
10247                 i += mono_array_length (fields);
10248         *p++ = i & 0xff;
10249         *p++ = (i >> 8) & 0xff;
10250         if (properties) {
10251                 MonoObject *prop;
10252                 for (i = 0; i < mono_array_length (properties); ++i) {
10253                         MonoType *ptype;
10254                         char *pname;
10255
10256                         prop = mono_array_get (properties, gpointer, i);
10257                         get_prop_name_and_type (prop, &pname, &ptype);
10258                         *p++ = 0x54; /* PROPERTY signature */
10259                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10260                         g_free (pname);
10261                 }
10262         }
10263
10264         if (fields) {
10265                 MonoObject *field;
10266                 for (i = 0; i < mono_array_length (fields); ++i) {
10267                         MonoType *ftype;
10268                         char *fname;
10269
10270                         field = mono_array_get (fields, gpointer, i);
10271                         get_field_name_and_type (field, &fname, &ftype);
10272                         *p++ = 0x53; /* FIELD signature */
10273                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10274                         g_free (fname);
10275                 }
10276         }
10277
10278         g_assert (p - buffer <= buflen);
10279         buflen = p - buffer;
10280         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10281         p = mono_array_addr (result, char, 0);
10282         memcpy (p, buffer, buflen);
10283         g_free (buffer);
10284         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10285                 g_free (sig);
10286         return result;
10287 }
10288
10289 /*
10290  * mono_reflection_setup_internal_class:
10291  * @tb: a TypeBuilder object
10292  *
10293  * Creates a MonoClass that represents the TypeBuilder.
10294  * This is a trick that lets us simplify a lot of reflection code
10295  * (and will allow us to support Build and Run assemblies easier).
10296  */
10297 void
10298 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10299 {
10300         MonoError error;
10301         MonoClass *klass, *parent;
10302
10303         RESOLVE_TYPE (tb->parent);
10304
10305         mono_loader_lock ();
10306
10307         if (tb->parent) {
10308                 /* check so we can compile corlib correctly */
10309                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10310                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10311                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10312                 } else {
10313                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10314                 }
10315         } else {
10316                 parent = NULL;
10317         }
10318         
10319         /* the type has already being created: it means we just have to change the parent */
10320         if (tb->type.type) {
10321                 klass = mono_class_from_mono_type (tb->type.type);
10322                 klass->parent = NULL;
10323                 /* fool mono_class_setup_parent */
10324                 klass->supertypes = NULL;
10325                 mono_class_setup_parent (klass, parent);
10326                 mono_class_setup_mono_type (klass);
10327                 mono_loader_unlock ();
10328                 return;
10329         }
10330
10331         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10332
10333         klass->image = &tb->module->dynamic_image->image;
10334
10335         klass->inited = 1; /* we lie to the runtime */
10336         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10337         if (!mono_error_ok (&error))
10338                 goto failure;
10339         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10340         if (!mono_error_ok (&error))
10341                 goto failure;
10342         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10343         klass->flags = tb->attrs;
10344         
10345         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10346
10347         klass->element_class = klass;
10348
10349         if (mono_class_get_ref_info (klass) == NULL) {
10350
10351                 mono_class_set_ref_info (klass, tb);
10352
10353                 /* Put into cache so mono_class_get_checked () will find it.
10354                 Skip nested types as those should not be available on the global scope. */
10355                 if (!tb->nesting_type)
10356                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10357
10358                 /*
10359                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10360                 by performing a mono_class_get which does the full resolution.
10361
10362                 Working around this semantics would require us to write a lot of code for no clear advantage.
10363                 */
10364                 mono_image_append_class_to_reflection_info_set (klass);
10365         } else {
10366                 g_assert (mono_class_get_ref_info (klass) == tb);
10367         }
10368
10369         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10370
10371         if (parent != NULL) {
10372                 mono_class_setup_parent (klass, parent);
10373         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10374                 const char *old_n = klass->name;
10375                 /* trick to get relative numbering right when compiling corlib */
10376                 klass->name = "BuildingObject";
10377                 mono_class_setup_parent (klass, mono_defaults.object_class);
10378                 klass->name = old_n;
10379         }
10380
10381         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10382                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10383                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10384                 klass->instance_size = sizeof (MonoObject);
10385                 klass->size_inited = 1;
10386                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10387         }
10388
10389         mono_class_setup_mono_type (klass);
10390
10391         mono_class_setup_supertypes (klass);
10392
10393         /*
10394          * FIXME: handle interfaces.
10395          */
10396
10397         tb->type.type = &klass->byval_arg;
10398
10399         if (tb->nesting_type) {
10400                 g_assert (tb->nesting_type->type);
10401                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10402         }
10403
10404         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10405
10406         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10407         
10408         mono_loader_unlock ();
10409         return;
10410
10411 failure:
10412         mono_loader_unlock ();
10413         mono_error_raise_exception (&error);
10414 }
10415
10416 /*
10417  * mono_reflection_setup_generic_class:
10418  * @tb: a TypeBuilder object
10419  *
10420  * Setup the generic class before adding the first generic parameter.
10421  */
10422 void
10423 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10424 {
10425 }
10426
10427 /*
10428  * mono_reflection_create_generic_class:
10429  * @tb: a TypeBuilder object
10430  *
10431  * Creates the generic class after all generic parameters have been added.
10432  */
10433 void
10434 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10435 {
10436         MonoClass *klass;
10437         int count, i;
10438
10439         klass = mono_class_from_mono_type (tb->type.type);
10440
10441         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10442
10443         if (klass->generic_container || (count == 0))
10444                 return;
10445
10446         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10447
10448         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10449
10450         klass->generic_container->owner.klass = klass;
10451         klass->generic_container->type_argc = count;
10452         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10453
10454         klass->is_generic = 1;
10455
10456         for (i = 0; i < count; i++) {
10457                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10458                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10459                 klass->generic_container->type_params [i] = *param;
10460                 /*Make sure we are a diferent type instance */
10461                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10462                 klass->generic_container->type_params [i].info.pklass = NULL;
10463                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10464
10465                 g_assert (klass->generic_container->type_params [i].param.owner);
10466         }
10467
10468         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10469 }
10470
10471 /*
10472  * mono_reflection_create_internal_class:
10473  * @tb: a TypeBuilder object
10474  *
10475  * Actually create the MonoClass that is associated with the TypeBuilder.
10476  */
10477 void
10478 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10479 {
10480         MonoClass *klass;
10481
10482         klass = mono_class_from_mono_type (tb->type.type);
10483
10484         mono_loader_lock ();
10485         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10486                 MonoReflectionFieldBuilder *fb;
10487                 MonoClass *ec;
10488                 MonoType *enum_basetype;
10489
10490                 g_assert (tb->fields != NULL);
10491                 g_assert (mono_array_length (tb->fields) >= 1);
10492
10493                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10494
10495                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10496                         mono_loader_unlock ();
10497                         return;
10498                 }
10499
10500                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10501                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10502                 if (!klass->element_class)
10503                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10504
10505                 /*
10506                  * get the element_class from the current corlib.
10507                  */
10508                 ec = default_class_from_mono_type (enum_basetype);
10509                 klass->instance_size = ec->instance_size;
10510                 klass->size_inited = 1;
10511                 /* 
10512                  * this is almost safe to do with enums and it's needed to be able
10513                  * to create objects of the enum type (for use in SetConstant).
10514                  */
10515                 /* FIXME: Does this mean enums can't have method overrides ? */
10516                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10517         }
10518         mono_loader_unlock ();
10519 }
10520
10521 static MonoMarshalSpec*
10522 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10523                                                                 MonoReflectionMarshal *minfo)
10524 {
10525         MonoMarshalSpec *res;
10526
10527         res = image_g_new0 (image, MonoMarshalSpec, 1);
10528         res->native = minfo->type;
10529
10530         switch (minfo->type) {
10531         case MONO_NATIVE_LPARRAY:
10532                 res->data.array_data.elem_type = minfo->eltype;
10533                 if (minfo->has_size) {
10534                         res->data.array_data.param_num = minfo->param_num;
10535                         res->data.array_data.num_elem = minfo->count;
10536                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10537                 }
10538                 else {
10539                         res->data.array_data.param_num = -1;
10540                         res->data.array_data.num_elem = -1;
10541                         res->data.array_data.elem_mult = -1;
10542                 }
10543                 break;
10544
10545         case MONO_NATIVE_BYVALTSTR:
10546         case MONO_NATIVE_BYVALARRAY:
10547                 res->data.array_data.num_elem = minfo->count;
10548                 break;
10549
10550         case MONO_NATIVE_CUSTOM:
10551                 if (minfo->marshaltyperef)
10552                         res->data.custom_data.custom_name =
10553                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10554                 if (minfo->mcookie)
10555                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10556                 break;
10557
10558         default:
10559                 break;
10560         }
10561
10562         return res;
10563 }
10564 #endif /* !DISABLE_REFLECTION_EMIT */
10565
10566 MonoReflectionMarshalAsAttribute*
10567 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10568                                                                                    MonoMarshalSpec *spec)
10569 {
10570         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10571         MonoReflectionMarshalAsAttribute *minfo;
10572         MonoType *mtype;
10573
10574         if (!System_Reflection_Emit_MarshalAsAttribute) {
10575                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10576                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10577                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10578         }
10579
10580         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10581         minfo->utype = spec->native;
10582
10583         switch (minfo->utype) {
10584         case MONO_NATIVE_LPARRAY:
10585                 minfo->array_subtype = spec->data.array_data.elem_type;
10586                 minfo->size_const = spec->data.array_data.num_elem;
10587                 if (spec->data.array_data.param_num != -1)
10588                         minfo->size_param_index = spec->data.array_data.param_num;
10589                 break;
10590
10591         case MONO_NATIVE_BYVALTSTR:
10592         case MONO_NATIVE_BYVALARRAY:
10593                 minfo->size_const = spec->data.array_data.num_elem;
10594                 break;
10595
10596         case MONO_NATIVE_CUSTOM:
10597                 if (spec->data.custom_data.custom_name) {
10598                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10599                         if (mtype)
10600                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10601
10602                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10603                 }
10604                 if (spec->data.custom_data.cookie)
10605                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10606                 break;
10607
10608         default:
10609                 break;
10610         }
10611
10612         return minfo;
10613 }
10614
10615 #ifndef DISABLE_REFLECTION_EMIT
10616 static MonoMethod*
10617 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10618                                          ReflectionMethodBuilder *rmb,
10619                                          MonoMethodSignature *sig)
10620 {
10621         MonoError error;
10622         MonoMethod *m;
10623         MonoMethodWrapper *wrapperm;
10624         MonoMarshalSpec **specs;
10625         MonoReflectionMethodAux *method_aux;
10626         MonoImage *image;
10627         gboolean dynamic;
10628         int i;
10629
10630         mono_error_init (&error);
10631         /*
10632          * Methods created using a MethodBuilder should have their memory allocated
10633          * inside the image mempool, while dynamic methods should have their memory
10634          * malloc'd.
10635          */
10636         dynamic = rmb->refs != NULL;
10637         image = dynamic ? NULL : klass->image;
10638
10639         if (!dynamic)
10640                 g_assert (!klass->generic_class);
10641
10642         mono_loader_lock ();
10643
10644         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10645                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10646                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10647         else
10648                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10649
10650         wrapperm = (MonoMethodWrapper*)m;
10651
10652         m->dynamic = dynamic;
10653         m->slot = -1;
10654         m->flags = rmb->attrs;
10655         m->iflags = rmb->iattrs;
10656         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10657         m->klass = klass;
10658         m->signature = sig;
10659         m->sre_method = TRUE;
10660         m->skip_visibility = rmb->skip_visibility;
10661         if (rmb->table_idx)
10662                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10663
10664         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10665                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10666                         m->string_ctor = 1;
10667
10668                 m->signature->pinvoke = 1;
10669         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10670                 m->signature->pinvoke = 1;
10671
10672                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10673
10674                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10675                 g_assert (mono_error_ok (&error));
10676                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10677                 g_assert (mono_error_ok (&error));
10678                 
10679                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10680
10681                 if (image_is_dynamic (klass->image))
10682                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10683
10684                 mono_loader_unlock ();
10685
10686                 return m;
10687         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10688                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10689                 MonoMethodHeader *header;
10690                 guint32 code_size;
10691                 gint32 max_stack, i;
10692                 gint32 num_locals = 0;
10693                 gint32 num_clauses = 0;
10694                 guint8 *code;
10695
10696                 if (rmb->ilgen) {
10697                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10698                         code_size = rmb->ilgen->code_len;
10699                         max_stack = rmb->ilgen->max_stack;
10700                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10701                         if (rmb->ilgen->ex_handlers)
10702                                 num_clauses = method_count_clauses (rmb->ilgen);
10703                 } else {
10704                         if (rmb->code) {
10705                                 code = mono_array_addr (rmb->code, guint8, 0);
10706                                 code_size = mono_array_length (rmb->code);
10707                                 /* we probably need to run a verifier on the code... */
10708                                 max_stack = 8; 
10709                         }
10710                         else {
10711                                 code = NULL;
10712                                 code_size = 0;
10713                                 max_stack = 8;
10714                         }
10715                 }
10716
10717                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10718                 header->code_size = code_size;
10719                 header->code = image_g_malloc (image, code_size);
10720                 memcpy ((char*)header->code, code, code_size);
10721                 header->max_stack = max_stack;
10722                 header->init_locals = rmb->init_locals;
10723                 header->num_locals = num_locals;
10724
10725                 for (i = 0; i < num_locals; ++i) {
10726                         MonoReflectionLocalBuilder *lb = 
10727                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10728
10729                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10730                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10731                 }
10732
10733                 header->num_clauses = num_clauses;
10734                 if (num_clauses) {
10735                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10736                                  rmb->ilgen, num_clauses);
10737                 }
10738
10739                 wrapperm->header = header;
10740         }
10741
10742         if (rmb->generic_params) {
10743                 int count = mono_array_length (rmb->generic_params);
10744                 MonoGenericContainer *container = rmb->generic_container;
10745
10746                 g_assert (container);
10747
10748                 container->type_argc = count;
10749                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10750                 container->owner.method = m;
10751                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10752
10753                 m->is_generic = TRUE;
10754                 mono_method_set_generic_container (m, container);
10755
10756                 for (i = 0; i < count; i++) {
10757                         MonoReflectionGenericParam *gp =
10758                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10759                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10760                         container->type_params [i] = *param;
10761                 }
10762
10763                 /*
10764                  * The method signature might have pointers to generic parameters that belong to other methods.
10765                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10766                  * generic parameters.
10767                  */
10768                 for (i = 0; i < m->signature->param_count; ++i) {
10769                         MonoType *t = m->signature->params [i];
10770                         if (t->type == MONO_TYPE_MVAR) {
10771                                 MonoGenericParam *gparam =  t->data.generic_param;
10772                                 if (gparam->num < count) {
10773                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10774                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10775                                 }
10776
10777                         }
10778                 }
10779
10780                 if (klass->generic_container) {
10781                         container->parent = klass->generic_container;
10782                         container->context.class_inst = klass->generic_container->context.class_inst;
10783                 }
10784                 container->context.method_inst = mono_get_shared_generic_inst (container);
10785         }
10786
10787         if (rmb->refs) {
10788                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10789                 int i;
10790                 void **data;
10791
10792                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10793
10794                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10795                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10796                 for (i = 0; i < rmb->nrefs; ++i)
10797                         data [i + 1] = rmb->refs [i];
10798         }
10799
10800         method_aux = NULL;
10801
10802         /* Parameter info */
10803         if (rmb->pinfo) {
10804                 if (!method_aux)
10805                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10806                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10807                 for (i = 0; i <= m->signature->param_count; ++i) {
10808                         MonoReflectionParamBuilder *pb;
10809                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10810                                 if ((i > 0) && (pb->attrs)) {
10811                                         /* Make a copy since it might point to a shared type structure */
10812                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10813                                         m->signature->params [i - 1]->attrs = pb->attrs;
10814                                 }
10815
10816                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10817                                         MonoDynamicImage *assembly;
10818                                         guint32 idx, def_type, len;
10819                                         char *p;
10820                                         const char *p2;
10821
10822                                         if (!method_aux->param_defaults) {
10823                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10824                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10825                                         }
10826                                         assembly = (MonoDynamicImage*)klass->image;
10827                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10828                                         /* Copy the data from the blob since it might get realloc-ed */
10829                                         p = assembly->blob.data + idx;
10830                                         len = mono_metadata_decode_blob_size (p, &p2);
10831                                         len += p2 - p;
10832                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10833                                         method_aux->param_default_types [i] = def_type;
10834                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10835                                 }
10836
10837                                 if (pb->name) {
10838                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10839                                         g_assert (mono_error_ok (&error));
10840                                 }
10841                                 if (pb->cattrs) {
10842                                         if (!method_aux->param_cattr)
10843                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10844                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10845                                 }
10846                         }
10847                 }
10848         }
10849
10850         /* Parameter marshalling */
10851         specs = NULL;
10852         if (rmb->pinfo)         
10853                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10854                         MonoReflectionParamBuilder *pb;
10855                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10856                                 if (pb->marshal_info) {
10857                                         if (specs == NULL)
10858                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10859                                         specs [pb->position] = 
10860                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10861                                 }
10862                         }
10863                 }
10864         if (specs != NULL) {
10865                 if (!method_aux)
10866                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10867                 method_aux->param_marshall = specs;
10868         }
10869
10870         if (image_is_dynamic (klass->image) && method_aux)
10871                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10872
10873         mono_loader_unlock ();
10874
10875         return m;
10876 }       
10877
10878 static MonoMethod*
10879 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10880 {
10881         ReflectionMethodBuilder rmb;
10882         MonoMethodSignature *sig;
10883
10884         mono_loader_lock ();
10885         sig = ctor_builder_to_signature (klass->image, mb);
10886         mono_loader_unlock ();
10887
10888         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10889
10890         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10891         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10892
10893         /* If we are in a generic class, we might be called multiple times from inflate_method */
10894         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10895                 /* ilgen is no longer needed */
10896                 mb->ilgen = NULL;
10897         }
10898
10899         return mb->mhandle;
10900 }
10901
10902 static MonoMethod*
10903 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10904 {
10905         ReflectionMethodBuilder rmb;
10906         MonoMethodSignature *sig;
10907
10908         mono_loader_lock ();
10909         sig = method_builder_to_signature (klass->image, mb);
10910         mono_loader_unlock ();
10911
10912         reflection_methodbuilder_from_method_builder (&rmb, mb);
10913
10914         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10915         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10916
10917         /* If we are in a generic class, we might be called multiple times from inflate_method */
10918         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10919                 /* ilgen is no longer needed */
10920                 mb->ilgen = NULL;
10921         }
10922         return mb->mhandle;
10923 }
10924
10925 static MonoClassField*
10926 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10927 {
10928         MonoClassField *field;
10929         MonoType *custom;
10930         MonoError error;
10931
10932         field = g_new0 (MonoClassField, 1);
10933
10934         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10935         g_assert (mono_error_ok (&error));
10936         if (fb->attrs || fb->modreq || fb->modopt) {
10937                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10938                 field->type->attrs = fb->attrs;
10939
10940                 g_assert (image_is_dynamic (klass->image));
10941                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10942                 g_free (field->type);
10943                 field->type = mono_metadata_type_dup (klass->image, custom);
10944                 g_free (custom);
10945         } else {
10946                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10947         }
10948         if (fb->offset != -1)
10949                 field->offset = fb->offset;
10950         field->parent = klass;
10951         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10952
10953         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10954
10955         return field;
10956 }
10957 #endif
10958
10959 MonoType*
10960 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10961 {
10962         MonoClass *klass;
10963         MonoReflectionTypeBuilder *tb = NULL;
10964         gboolean is_dynamic = FALSE;
10965         MonoClass *geninst;
10966
10967         mono_loader_lock ();
10968
10969         if (is_sre_type_builder (mono_object_class (type))) {
10970                 tb = (MonoReflectionTypeBuilder *) type;
10971
10972                 is_dynamic = TRUE;
10973         } else if (is_sre_generic_instance (mono_object_class (type))) {
10974                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10975                 MonoReflectionType *gtd = rgi->generic_type;
10976
10977                 if (is_sre_type_builder (mono_object_class (gtd))) {
10978                         tb = (MonoReflectionTypeBuilder *)gtd;
10979                         is_dynamic = TRUE;
10980                 }
10981         }
10982
10983         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10984         if (tb && tb->generic_container)
10985                 mono_reflection_create_generic_class (tb);
10986
10987         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10988         if (!klass->generic_container) {
10989                 mono_loader_unlock ();
10990                 return NULL;
10991         }
10992
10993         if (klass->wastypebuilder) {
10994                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10995
10996                 is_dynamic = TRUE;
10997         }
10998
10999         mono_loader_unlock ();
11000
11001         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11002
11003         return &geninst->byval_arg;
11004 }
11005
11006 MonoClass*
11007 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11008 {
11009         MonoGenericClass *gclass;
11010         MonoGenericInst *inst;
11011
11012         g_assert (klass->generic_container);
11013
11014         inst = mono_metadata_get_generic_inst (type_argc, types);
11015         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11016
11017         return mono_generic_class_get_class (gclass);
11018 }
11019
11020 MonoReflectionMethod*
11021 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11022 {
11023         MonoError error;
11024         MonoClass *klass;
11025         MonoMethod *method, *inflated;
11026         MonoMethodInflated *imethod;
11027         MonoGenericContext tmp_context;
11028         MonoGenericInst *ginst;
11029         MonoType **type_argv;
11030         int count, i;
11031
11032         /*FIXME but this no longer should happen*/
11033         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11034 #ifndef DISABLE_REFLECTION_EMIT
11035                 MonoReflectionMethodBuilder *mb = NULL;
11036                 MonoReflectionTypeBuilder *tb;
11037                 MonoClass *klass;
11038
11039                 mb = (MonoReflectionMethodBuilder *) rmethod;
11040                 tb = (MonoReflectionTypeBuilder *) mb->type;
11041                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11042
11043                 method = methodbuilder_to_mono_method (klass, mb);
11044 #else
11045                 g_assert_not_reached ();
11046                 method = NULL;
11047 #endif
11048         } else {
11049                 method = rmethod->method;
11050         }
11051
11052         klass = method->klass;
11053
11054         if (method->is_inflated)
11055                 method = ((MonoMethodInflated *) method)->declaring;
11056
11057         count = mono_method_signature (method)->generic_param_count;
11058         if (count != mono_array_length (types))
11059                 return NULL;
11060
11061         type_argv = g_new0 (MonoType *, count);
11062         for (i = 0; i < count; i++) {
11063                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
11064                 type_argv [i] = mono_reflection_type_get_handle (garg);
11065         }
11066         ginst = mono_metadata_get_generic_inst (count, type_argv);
11067         g_free (type_argv);
11068
11069         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11070         tmp_context.method_inst = ginst;
11071
11072         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11073         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11074         imethod = (MonoMethodInflated *) inflated;
11075
11076         /*FIXME but I think this is no longer necessary*/
11077         if (image_is_dynamic (method->klass->image)) {
11078                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11079                 /*
11080                  * This table maps metadata structures representing inflated methods/fields
11081                  * to the reflection objects representing their generic definitions.
11082                  */
11083                 mono_image_lock ((MonoImage*)image);
11084                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11085                 mono_image_unlock ((MonoImage*)image);
11086         }
11087
11088         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11089                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11090         
11091         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11092 }
11093
11094 #ifndef DISABLE_REFLECTION_EMIT
11095
11096 static MonoMethod *
11097 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11098 {
11099         MonoMethodInflated *imethod;
11100         MonoGenericContext *context;
11101         int i;
11102
11103         /*
11104          * With generic code sharing the klass might not be inflated.
11105          * This can happen because classes inflated with their own
11106          * type arguments are "normalized" to the uninflated class.
11107          */
11108         if (!klass->generic_class)
11109                 return method;
11110
11111         context = mono_class_get_context (klass);
11112
11113         if (klass->method.count && klass->methods) {
11114                 /* Find the already created inflated method */
11115                 for (i = 0; i < klass->method.count; ++i) {
11116                         g_assert (klass->methods [i]->is_inflated);
11117                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11118                                 break;
11119                 }
11120                 g_assert (i < klass->method.count);
11121                 imethod = (MonoMethodInflated*)klass->methods [i];
11122         } else {
11123                 MonoError error;
11124                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11125                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11126         }
11127
11128         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11129                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11130
11131                 mono_image_lock ((MonoImage*)image);
11132                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11133                 mono_image_unlock ((MonoImage*)image);
11134         }
11135         return (MonoMethod *) imethod;
11136 }
11137
11138 static MonoMethod *
11139 inflate_method (MonoReflectionType *type, MonoObject *obj)
11140 {
11141         MonoMethod *method;
11142         MonoClass *gklass;
11143
11144         MonoClass *type_class = mono_object_class (type);
11145
11146         if (is_sre_generic_instance (type_class)) {
11147                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11148                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11149         } else if (is_sre_type_builder (type_class)) {
11150                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11151         } else if (type->type) {
11152                 gklass = mono_class_from_mono_type (type->type);
11153                 gklass = mono_class_get_generic_type_definition (gklass);
11154         } else {
11155                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11156         }
11157
11158         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11159                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11160                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11161                 else
11162                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11163         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11164                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11165         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11166                 method = ((MonoReflectionMethod *) obj)->method;
11167         else {
11168                 method = NULL; /* prevent compiler warning */
11169                 g_error ("can't handle type %s", obj->vtable->klass->name);
11170         }
11171
11172         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11173 }
11174
11175 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11176 void
11177 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11178 {
11179         MonoGenericClass *gclass;
11180         MonoDynamicGenericClass *dgclass;
11181         MonoClass *klass, *gklass;
11182         MonoType *gtype;
11183         int i;
11184
11185         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11186         klass = mono_class_from_mono_type (gtype);
11187         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11188         gclass = gtype->data.generic_class;
11189
11190         if (!gclass->is_dynamic)
11191                 return;
11192
11193         dgclass = (MonoDynamicGenericClass *) gclass;
11194
11195         if (dgclass->initialized)
11196                 return;
11197
11198         gklass = gclass->container_class;
11199         mono_class_init (gklass);
11200
11201         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11202
11203         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11204         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11205         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11206
11207         for (i = 0; i < dgclass->count_fields; i++) {
11208                 MonoObject *obj = mono_array_get (fields, gpointer, i);
11209                 MonoClassField *field, *inflated_field = NULL;
11210
11211                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11212                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11213                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11214                         field = ((MonoReflectionField *) obj)->field;
11215                 else {
11216                         field = NULL; /* prevent compiler warning */
11217                         g_assert_not_reached ();
11218                 }
11219
11220                 dgclass->fields [i] = *field;
11221                 dgclass->fields [i].parent = klass;
11222                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11223                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11224                 dgclass->field_generic_types [i] = field->type;
11225                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11226                 dgclass->field_objects [i] = obj;
11227
11228                 if (inflated_field) {
11229                         g_free (inflated_field);
11230                 } else {
11231                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11232                 }
11233         }
11234
11235         dgclass->initialized = TRUE;
11236 }
11237
11238 void
11239 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11240 {
11241         MonoDynamicGenericClass *dgclass;
11242         int i;
11243
11244         g_assert (gclass->is_dynamic);
11245
11246         dgclass = (MonoDynamicGenericClass *)gclass;
11247
11248         for (i = 0; i < dgclass->count_fields; ++i) {
11249                 MonoClassField *field = dgclass->fields + i;
11250                 mono_metadata_free_type (field->type);
11251                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11252         }
11253 }
11254
11255 static void
11256 fix_partial_generic_class (MonoClass *klass)
11257 {
11258         MonoClass *gklass = klass->generic_class->container_class;
11259         MonoDynamicGenericClass *dgclass;
11260         int i;
11261
11262         if (klass->wastypebuilder)
11263                 return;
11264
11265         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11266         if (klass->parent != gklass->parent) {
11267                 MonoError error;
11268                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11269                 if (mono_error_ok (&error)) {
11270                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11271                         mono_metadata_free_type (parent_type);
11272                         if (parent != klass->parent) {
11273                                 /*fool mono_class_setup_parent*/
11274                                 klass->supertypes = NULL;
11275                                 mono_class_setup_parent (klass, parent);
11276                         }
11277                 } else {
11278                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11279                         mono_error_cleanup (&error);
11280                         if (gklass->wastypebuilder)
11281                                 klass->wastypebuilder = TRUE;
11282                         return;
11283                 }
11284         }
11285
11286         if (!dgclass->initialized)
11287                 return;
11288
11289         if (klass->method.count != gklass->method.count) {
11290                 klass->method.count = gklass->method.count;
11291                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11292
11293                 for (i = 0; i < klass->method.count; i++) {
11294                         MonoError error;
11295                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11296                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11297                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11298                 }
11299         }
11300
11301         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11302                 klass->interface_count = gklass->interface_count;
11303                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11304                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11305
11306                 for (i = 0; i < gklass->interface_count; ++i) {
11307                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11308                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11309                         mono_metadata_free_type (iface_type);
11310
11311                         ensure_runtime_vtable (klass->interfaces [i]);
11312                 }
11313                 klass->interfaces_inited = 1;
11314         }
11315
11316         if (klass->field.count != gklass->field.count) {
11317                 klass->field.count = gklass->field.count;
11318                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11319
11320                 for (i = 0; i < klass->field.count; i++) {
11321                         klass->fields [i] = gklass->fields [i];
11322                         klass->fields [i].parent = klass;
11323                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11324                 }
11325         }
11326
11327         /*We can only finish with this klass once it's parent has as well*/
11328         if (gklass->wastypebuilder)
11329                 klass->wastypebuilder = TRUE;
11330         return;
11331 }
11332
11333 static void
11334 ensure_generic_class_runtime_vtable (MonoClass *klass)
11335 {
11336         MonoClass *gklass = klass->generic_class->container_class;
11337
11338         ensure_runtime_vtable (gklass); 
11339
11340         fix_partial_generic_class (klass);
11341 }
11342
11343 static void
11344 ensure_runtime_vtable (MonoClass *klass)
11345 {
11346         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11347         int i, num, j;
11348
11349         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11350                 return;
11351         if (klass->parent)
11352                 ensure_runtime_vtable (klass->parent);
11353
11354         if (tb) {
11355                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11356                 num += tb->num_methods;
11357                 klass->method.count = num;
11358                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11359                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11360                 for (i = 0; i < num; ++i)
11361                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11362                 num = tb->num_methods;
11363                 j = i;
11364                 for (i = 0; i < num; ++i)
11365                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11366         
11367                 if (tb->interfaces) {
11368                         klass->interface_count = mono_array_length (tb->interfaces);
11369                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11370                         for (i = 0; i < klass->interface_count; ++i) {
11371                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11372                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11373                                 ensure_runtime_vtable (klass->interfaces [i]);
11374                         }
11375                         klass->interfaces_inited = 1;
11376                 }
11377         } else if (klass->generic_class){
11378                 ensure_generic_class_runtime_vtable (klass);
11379         }
11380
11381         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11382                 int slot_num = 0;
11383                 for (i = 0; i < klass->method.count; ++i) {
11384                         MonoMethod *im = klass->methods [i];
11385                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11386                                 im->slot = slot_num++;
11387                 }
11388                 
11389                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11390                 mono_class_setup_interface_offsets (klass);
11391                 mono_class_setup_interface_id (klass);
11392         }
11393
11394         /*
11395          * The generic vtable is needed even if image->run is not set since some
11396          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11397          * method->slot being defined.
11398          */
11399
11400         /* 
11401          * tb->methods could not be freed since it is used for determining 
11402          * overrides during dynamic vtable construction.
11403          */
11404 }
11405
11406 static MonoMethod*
11407 mono_reflection_method_get_handle (MonoObject *method)
11408 {
11409         MonoClass *klass = mono_object_class (method);
11410         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11411                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11412                 return sr_method->method;
11413         }
11414         if (is_sre_method_builder (klass)) {
11415                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11416                 return mb->mhandle;
11417         }
11418         if (is_sre_method_on_tb_inst (klass)) {
11419                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11420                 MonoMethod *result;
11421                 /*FIXME move this to a proper method and unify with resolve_object*/
11422                 if (m->method_args) {
11423                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11424                 } else {
11425                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11426                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11427                         MonoMethod *mono_method;
11428
11429                         if (is_sre_method_builder (mono_object_class (m->mb)))
11430                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11431                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11432                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11433                         else
11434                                 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)));
11435
11436                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11437                 }
11438                 return result;
11439         }
11440
11441         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11442         return NULL;
11443 }
11444
11445 void
11446 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11447 {
11448         MonoReflectionTypeBuilder *tb;
11449         int i, j, onum;
11450         MonoReflectionMethod *m;
11451
11452         *overrides = NULL;
11453         *num_overrides = 0;
11454
11455         g_assert (image_is_dynamic (klass->image));
11456
11457         if (!mono_class_get_ref_info (klass))
11458                 return;
11459
11460         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11461
11462         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11463
11464         onum = 0;
11465         if (tb->methods) {
11466                 for (i = 0; i < tb->num_methods; ++i) {
11467                         MonoReflectionMethodBuilder *mb = 
11468                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11469                         if (mb->override_methods)
11470                                 onum += mono_array_length (mb->override_methods);
11471                 }
11472         }
11473
11474         if (onum) {
11475                 *overrides = g_new0 (MonoMethod*, onum * 2);
11476
11477                 onum = 0;
11478                 for (i = 0; i < tb->num_methods; ++i) {
11479                         MonoReflectionMethodBuilder *mb = 
11480                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11481                         if (mb->override_methods) {
11482                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11483                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11484
11485                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11486                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11487
11488                                         g_assert (mb->mhandle);
11489
11490                                         onum ++;
11491                                 }
11492                         }
11493                 }
11494         }
11495
11496         *num_overrides = onum;
11497 }
11498
11499 static void
11500 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11501 {
11502         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11503         MonoReflectionFieldBuilder *fb;
11504         MonoClassField *field;
11505         MonoImage *image = klass->image;
11506         const char *p, *p2;
11507         int i;
11508         guint32 len, idx, real_size = 0;
11509
11510         klass->field.count = tb->num_fields;
11511         klass->field.first = 0;
11512
11513         mono_error_init (error);
11514
11515         if (tb->class_size) {
11516                 if ((tb->packing_size & 0xffffff00) != 0) {
11517                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11518                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11519                         return;
11520                 }
11521                 klass->packing_size = tb->packing_size;
11522                 real_size = klass->instance_size + tb->class_size;
11523         }
11524
11525         if (!klass->field.count) {
11526                 klass->instance_size = MAX (klass->instance_size, real_size);
11527                 return;
11528         }
11529         
11530         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11531         mono_class_alloc_ext (klass);
11532         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11533         /*
11534         This is, guess what, a hack.
11535         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11536         On the static path no field class is resolved, only types are built. This is the right thing to do
11537         but we suck.
11538         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11539         */
11540         klass->size_inited = 1;
11541
11542         for (i = 0; i < klass->field.count; ++i) {
11543                 MonoArray *rva_data;
11544                 fb = mono_array_get (tb->fields, gpointer, i);
11545                 field = &klass->fields [i];
11546                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11547                 if (!mono_error_ok (error))
11548                         return;
11549                 if (fb->attrs) {
11550                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11551                         field->type->attrs = fb->attrs;
11552                 } else {
11553                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11554                 }
11555
11556                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11557                         char *base = mono_array_addr (rva_data, char, 0);
11558                         size_t size = mono_array_length (rva_data);
11559                         char *data = mono_image_alloc (klass->image, size);
11560                         memcpy (data, base, size);
11561                         klass->ext->field_def_values [i].data = data;
11562                 }
11563                 if (fb->offset != -1)
11564                         field->offset = fb->offset;
11565                 field->parent = klass;
11566                 fb->handle = field;
11567                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11568
11569                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11570                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11571                 }
11572                 if (fb->def_value) {
11573                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11574                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11575                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11576                         /* Copy the data from the blob since it might get realloc-ed */
11577                         p = assembly->blob.data + idx;
11578                         len = mono_metadata_decode_blob_size (p, &p2);
11579                         len += p2 - p;
11580                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11581                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11582                 }
11583         }
11584
11585         klass->instance_size = MAX (klass->instance_size, real_size);
11586         mono_class_layout_fields (klass);
11587 }
11588
11589 static void
11590 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11591 {
11592         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11593         MonoReflectionPropertyBuilder *pb;
11594         MonoImage *image = klass->image;
11595         MonoProperty *properties;
11596         int i;
11597
11598         mono_error_init (error);
11599
11600         if (!klass->ext)
11601                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11602
11603         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11604         klass->ext->property.first = 0;
11605
11606         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11607         klass->ext->properties = properties;
11608         for (i = 0; i < klass->ext->property.count; ++i) {
11609                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11610                 properties [i].parent = klass;
11611                 properties [i].attrs = pb->attrs;
11612                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11613                 if (!mono_error_ok (error))
11614                         return;
11615                 if (pb->get_method)
11616                         properties [i].get = pb->get_method->mhandle;
11617                 if (pb->set_method)
11618                         properties [i].set = pb->set_method->mhandle;
11619
11620                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11621                 if (pb->def_value) {
11622                         guint32 len, idx;
11623                         const char *p, *p2;
11624                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11625                         if (!klass->ext->prop_def_values)
11626                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11627                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11628                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11629                         /* Copy the data from the blob since it might get realloc-ed */
11630                         p = assembly->blob.data + idx;
11631                         len = mono_metadata_decode_blob_size (p, &p2);
11632                         len += p2 - p;
11633                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11634                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11635                 }
11636         }
11637 }
11638
11639 MonoReflectionEvent *
11640 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11641 {
11642         MonoEvent *event = g_new0 (MonoEvent, 1);
11643         MonoClass *klass;
11644
11645         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11646
11647         event->parent = klass;
11648         event->attrs = eb->attrs;
11649         event->name = mono_string_to_utf8 (eb->name);
11650         if (eb->add_method)
11651                 event->add = eb->add_method->mhandle;
11652         if (eb->remove_method)
11653                 event->remove = eb->remove_method->mhandle;
11654         if (eb->raise_method)
11655                 event->raise = eb->raise_method->mhandle;
11656
11657 #ifndef MONO_SMALL_CONFIG
11658         if (eb->other_methods) {
11659                 int j;
11660                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11661                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11662                         MonoReflectionMethodBuilder *mb = 
11663                                 mono_array_get (eb->other_methods,
11664                                                 MonoReflectionMethodBuilder*, j);
11665                         event->other [j] = mb->mhandle;
11666                 }
11667         }
11668 #endif
11669
11670         return mono_event_get_object (mono_object_domain (tb), klass, event);
11671 }
11672
11673 static void
11674 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11675 {
11676         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11677         MonoReflectionEventBuilder *eb;
11678         MonoImage *image = klass->image;
11679         MonoEvent *events;
11680         int i;
11681
11682         mono_error_init (error);
11683
11684         if (!klass->ext)
11685                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11686
11687         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11688         klass->ext->event.first = 0;
11689
11690         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11691         klass->ext->events = events;
11692         for (i = 0; i < klass->ext->event.count; ++i) {
11693                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11694                 events [i].parent = klass;
11695                 events [i].attrs = eb->attrs;
11696                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11697                 if (!mono_error_ok (error))
11698                         return;
11699                 if (eb->add_method)
11700                         events [i].add = eb->add_method->mhandle;
11701                 if (eb->remove_method)
11702                         events [i].remove = eb->remove_method->mhandle;
11703                 if (eb->raise_method)
11704                         events [i].raise = eb->raise_method->mhandle;
11705
11706 #ifndef MONO_SMALL_CONFIG
11707                 if (eb->other_methods) {
11708                         int j;
11709                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11710                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11711                                 MonoReflectionMethodBuilder *mb = 
11712                                         mono_array_get (eb->other_methods,
11713                                                                         MonoReflectionMethodBuilder*, j);
11714                                 events [i].other [j] = mb->mhandle;
11715                         }
11716                 }
11717 #endif
11718                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11719         }
11720 }
11721
11722 static gboolean
11723 remove_instantiations_of_and_ensure_contents (gpointer key,
11724                                                   gpointer value,
11725                                                   gpointer user_data)
11726 {
11727         MonoType *type = (MonoType*)key;
11728         MonoClass *klass = (MonoClass*)user_data;
11729
11730         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11731                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11732                 return TRUE;
11733         } else
11734                 return FALSE;
11735 }
11736
11737 static void
11738 check_array_for_usertypes (MonoArray *arr)
11739 {
11740         int i;
11741
11742         if (!arr)
11743                 return;
11744
11745         for (i = 0; i < mono_array_length (arr); ++i)
11746                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11747 }
11748
11749 MonoReflectionType*
11750 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11751 {
11752         MonoError error;
11753         MonoClass *klass;
11754         MonoDomain* domain;
11755         MonoReflectionType* res;
11756         int i, j;
11757
11758         domain = mono_object_domain (tb);
11759         klass = mono_class_from_mono_type (tb->type.type);
11760
11761         /*
11762          * Check for user defined Type subclasses.
11763          */
11764         RESOLVE_TYPE (tb->parent);
11765         check_array_for_usertypes (tb->interfaces);
11766         if (tb->fields) {
11767                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11768                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11769                         if (fb) {
11770                                 RESOLVE_TYPE (fb->type);
11771                                 check_array_for_usertypes (fb->modreq);
11772                                 check_array_for_usertypes (fb->modopt);
11773                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11774                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11775                         }
11776                 }
11777         }
11778         if (tb->methods) {
11779                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11780                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11781                         if (mb) {
11782                                 RESOLVE_TYPE (mb->rtype);
11783                                 check_array_for_usertypes (mb->return_modreq);
11784                                 check_array_for_usertypes (mb->return_modopt);
11785                                 check_array_for_usertypes (mb->parameters);
11786                                 if (mb->param_modreq)
11787                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11788                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11789                                 if (mb->param_modopt)
11790                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11791                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11792                         }
11793                 }
11794         }
11795         if (tb->ctors) {
11796                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11797                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11798                         if (mb) {
11799                                 check_array_for_usertypes (mb->parameters);
11800                                 if (mb->param_modreq)
11801                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11802                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11803                                 if (mb->param_modopt)
11804                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11805                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11806                         }
11807                 }
11808         }
11809
11810         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11811
11812         /* 
11813          * we need to lock the domain because the lock will be taken inside
11814          * So, we need to keep the locking order correct.
11815          */
11816         mono_loader_lock ();
11817         mono_domain_lock (domain);
11818         if (klass->wastypebuilder) {
11819                 mono_domain_unlock (domain);
11820                 mono_loader_unlock ();
11821                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11822         }
11823         /*
11824          * Fields to set in klass:
11825          * the various flags: delegate/unicode/contextbound etc.
11826          */
11827         klass->flags = tb->attrs;
11828         klass->has_cctor = 1;
11829         klass->has_finalize = 1;
11830         klass->has_finalize_inited = 1;
11831
11832         mono_class_setup_parent (klass, klass->parent);
11833         /* fool mono_class_setup_supertypes */
11834         klass->supertypes = NULL;
11835         mono_class_setup_supertypes (klass);
11836         mono_class_setup_mono_type (klass);
11837
11838 #if 0
11839         if (!((MonoDynamicImage*)klass->image)->run) {
11840                 if (klass->generic_container) {
11841                         /* FIXME: The code below can't handle generic classes */
11842                         klass->wastypebuilder = TRUE;
11843                         mono_loader_unlock ();
11844                         mono_domain_unlock (domain);
11845                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11846                 }
11847         }
11848 #endif
11849
11850         /* enums are done right away */
11851         if (!klass->enumtype)
11852                 ensure_runtime_vtable (klass);
11853
11854         if (tb->subtypes) {
11855                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11856                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11857                         mono_class_alloc_ext (klass);
11858                         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)));
11859                 }
11860         }
11861
11862         klass->nested_classes_inited = TRUE;
11863
11864         /* fields and object layout */
11865         if (klass->parent) {
11866                 if (!klass->parent->size_inited)
11867                         mono_class_init (klass->parent);
11868                 klass->instance_size = klass->parent->instance_size;
11869                 klass->sizes.class_size = 0;
11870                 klass->min_align = klass->parent->min_align;
11871                 /* if the type has no fields we won't call the field_setup
11872                  * routine which sets up klass->has_references.
11873                  */
11874                 klass->has_references |= klass->parent->has_references;
11875         } else {
11876                 klass->instance_size = sizeof (MonoObject);
11877                 klass->min_align = 1;
11878         }
11879
11880         /* FIXME: handle packing_size and instance_size */
11881         typebuilder_setup_fields (klass, &error);
11882         if (!mono_error_ok (&error))
11883                 goto failure;
11884         typebuilder_setup_properties (klass, &error);
11885         if (!mono_error_ok (&error))
11886                 goto failure;
11887
11888         typebuilder_setup_events (klass, &error);
11889         if (!mono_error_ok (&error))
11890                 goto failure;
11891
11892         klass->wastypebuilder = TRUE;
11893
11894         /* 
11895          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11896          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11897          * we want to return normal System.MonoType objects, so clear these out from the cache.
11898          *
11899          * Together with this we must ensure the contents of all instances to match the created type.
11900          */
11901         if (domain->type_hash && klass->generic_container)
11902                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11903
11904         mono_domain_unlock (domain);
11905         mono_loader_unlock ();
11906
11907         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11908                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11909                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11910         }
11911
11912         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11913         g_assert (res != (MonoReflectionType*)tb);
11914
11915         return res;
11916
11917 failure:
11918         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11919         klass->wastypebuilder = TRUE;
11920         mono_domain_unlock (domain);
11921         mono_loader_unlock ();
11922         mono_error_raise_exception (&error);
11923         return NULL;
11924 }
11925
11926 void
11927 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11928 {
11929         MonoGenericParamFull *param;
11930         MonoImage *image;
11931         MonoClass *pklass;
11932         MonoError error;
11933
11934         image = &gparam->tbuilder->module->dynamic_image->image;
11935
11936         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11937
11938         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11939         g_assert (mono_error_ok (&error));
11940         param->param.num = gparam->index;
11941
11942         if (gparam->mbuilder) {
11943                 if (!gparam->mbuilder->generic_container) {
11944                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11945                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11946                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11947                         gparam->mbuilder->generic_container->is_method = TRUE;
11948                         /* 
11949                          * Cannot set owner.method, since the MonoMethod is not created yet.
11950                          * Set the image field instead, so type_in_image () works.
11951                          */
11952                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
11953                         gparam->mbuilder->generic_container->owner.image = klass->image;
11954                 }
11955                 param->param.owner = gparam->mbuilder->generic_container;
11956         } else if (gparam->tbuilder) {
11957                 if (!gparam->tbuilder->generic_container) {
11958                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11959                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11960                         gparam->tbuilder->generic_container->owner.klass = klass;
11961                 }
11962                 param->param.owner = gparam->tbuilder->generic_container;
11963         }
11964
11965         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
11966
11967         gparam->type.type = &pklass->byval_arg;
11968
11969         mono_class_set_ref_info (pklass, gparam);
11970         mono_image_append_class_to_reflection_info_set (pklass);
11971 }
11972
11973 MonoArray *
11974 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11975 {
11976         MonoReflectionModuleBuilder *module = sig->module;
11977         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11978         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11979         guint32 buflen, i;
11980         MonoArray *result;
11981         SigBuffer buf;
11982
11983         check_array_for_usertypes (sig->arguments);
11984
11985         sigbuffer_init (&buf, 32);
11986
11987         sigbuffer_add_value (&buf, 0x07);
11988         sigbuffer_add_value (&buf, na);
11989         if (assembly != NULL){
11990                 for (i = 0; i < na; ++i) {
11991                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11992                         encode_reflection_type (assembly, type, &buf);
11993                 }
11994         }
11995
11996         buflen = buf.p - buf.buf;
11997         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11998         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11999         sigbuffer_free (&buf);
12000
12001         return result;
12002 }
12003
12004 MonoArray *
12005 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12006 {
12007         MonoDynamicImage *assembly = sig->module->dynamic_image;
12008         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12009         guint32 buflen, i;
12010         MonoArray *result;
12011         SigBuffer buf;
12012
12013         check_array_for_usertypes (sig->arguments);
12014
12015         sigbuffer_init (&buf, 32);
12016
12017         sigbuffer_add_value (&buf, 0x06);
12018         for (i = 0; i < na; ++i) {
12019                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12020                 encode_reflection_type (assembly, type, &buf);
12021         }
12022
12023         buflen = buf.p - buf.buf;
12024         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12025         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12026         sigbuffer_free (&buf);
12027
12028         return result;
12029 }
12030
12031 typedef struct {
12032         MonoMethod *handle;
12033         MonoDomain *domain;
12034 } DynamicMethodReleaseData;
12035
12036 /*
12037  * The runtime automatically clean up those after finalization.
12038 */      
12039 static MonoReferenceQueue *dynamic_method_queue;
12040
12041 static void
12042 free_dynamic_method (void *dynamic_method)
12043 {
12044         DynamicMethodReleaseData *data = dynamic_method;
12045         MonoDomain *domain = data->domain;
12046         MonoMethod *method = data->handle;
12047         guint32 dis_link;
12048
12049         mono_domain_lock (domain);
12050         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12051         g_hash_table_remove (domain->method_to_dyn_method, method);
12052         mono_domain_unlock (domain);
12053         g_assert (dis_link);
12054         mono_gchandle_free (dis_link);
12055
12056         mono_runtime_free_method (domain, method);
12057         g_free (data);
12058 }
12059
12060 void 
12061 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12062 {
12063         MonoReferenceQueue *queue;
12064         MonoMethod *handle;
12065         DynamicMethodReleaseData *release_data;
12066         ReflectionMethodBuilder rmb;
12067         MonoMethodSignature *sig;
12068         MonoClass *klass;
12069         MonoDomain *domain;
12070         GSList *l;
12071         int i;
12072
12073         if (mono_runtime_is_shutting_down ())
12074                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12075
12076         if (!(queue = dynamic_method_queue)) {
12077                 mono_loader_lock ();
12078                 if (!(queue = dynamic_method_queue))
12079                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12080                 mono_loader_unlock ();
12081         }
12082
12083         sig = dynamic_method_to_signature (mb);
12084
12085         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12086
12087         /*
12088          * Resolve references.
12089          */
12090         /* 
12091          * Every second entry in the refs array is reserved for storing handle_class,
12092          * which is needed by the ldtoken implementation in the JIT.
12093          */
12094         rmb.nrefs = mb->nrefs;
12095         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12096         for (i = 0; i < mb->nrefs; i += 2) {
12097                 MonoClass *handle_class;
12098                 gpointer ref;
12099                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12100
12101                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12102                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12103                         /*
12104                          * The referenced DynamicMethod should already be created by the managed
12105                          * code, except in the case of circular references. In that case, we store
12106                          * method in the refs array, and fix it up later when the referenced 
12107                          * DynamicMethod is created.
12108                          */
12109                         if (method->mhandle) {
12110                                 ref = method->mhandle;
12111                         } else {
12112                                 /* FIXME: GC object stored in unmanaged memory */
12113                                 ref = method;
12114
12115                                 /* FIXME: GC object stored in unmanaged memory */
12116                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12117                         }
12118                         handle_class = mono_defaults.methodhandle_class;
12119                 } else {
12120                         MonoException *ex = NULL;
12121                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12122                         if (!ref)
12123                                 ex = mono_get_exception_type_load (NULL, NULL);
12124                         else if (mono_security_core_clr_enabled ())
12125                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12126
12127                         if (ex) {
12128                                 g_free (rmb.refs);
12129                                 mono_raise_exception (ex);
12130                                 return;
12131                         }
12132                 }
12133
12134                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12135                 rmb.refs [i + 1] = handle_class;
12136         }               
12137
12138         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12139
12140         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12141         release_data = g_new (DynamicMethodReleaseData, 1);
12142         release_data->handle = handle;
12143         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12144         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12145                 g_free (release_data);
12146
12147         /* Fix up refs entries pointing at us */
12148         for (l = mb->referenced_by; l; l = l->next) {
12149                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12150                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12151                 gpointer *data;
12152                 
12153                 g_assert (method->mhandle);
12154
12155                 data = (gpointer*)wrapper->method_data;
12156                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12157                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12158                                 data [i + 1] = mb->mhandle;
12159                 }
12160         }
12161         g_slist_free (mb->referenced_by);
12162
12163         g_free (rmb.refs);
12164
12165         /* ilgen is no longer needed */
12166         mb->ilgen = NULL;
12167
12168         domain = mono_domain_get ();
12169         mono_domain_lock (domain);
12170         if (!domain->method_to_dyn_method)
12171                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12172         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12173         mono_domain_unlock (domain);
12174 }
12175
12176 #endif /* DISABLE_REFLECTION_EMIT */
12177
12178 /**
12179  * 
12180  * mono_reflection_is_valid_dynamic_token:
12181  * 
12182  * Returns TRUE if token is valid.
12183  * 
12184  */
12185 gboolean
12186 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12187 {
12188         return lookup_dyn_token (image, token) != NULL;
12189 }
12190
12191 MonoMethodSignature *
12192 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12193 {
12194         MonoMethodSignature *sig;
12195         g_assert (image_is_dynamic (image));
12196
12197         mono_error_init (error);
12198
12199         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12200         if (sig)
12201                 return sig;
12202
12203         return mono_method_signature_checked (method, error);
12204 }
12205
12206 #ifndef DISABLE_REFLECTION_EMIT
12207
12208 /**
12209  * mono_reflection_lookup_dynamic_token:
12210  *
12211  * Finish the Builder object pointed to by TOKEN and return the corresponding
12212  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12213  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12214  * mapping table.
12215  *
12216  * LOCKING: Take the loader lock
12217  */
12218 gpointer
12219 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12220 {
12221         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12222         MonoObject *obj;
12223         MonoClass *klass;
12224
12225         obj = lookup_dyn_token (assembly, token);
12226         if (!obj) {
12227                 if (valid_token)
12228                         g_error ("Could not find required dynamic token 0x%08x", token);
12229                 else
12230                         return NULL;
12231         }
12232
12233         if (!handle_class)
12234                 handle_class = &klass;
12235         return resolve_object (image, obj, handle_class, context);
12236 }
12237
12238 /*
12239  * ensure_complete_type:
12240  *
12241  *   Ensure that KLASS is completed if it is a dynamic type, or references
12242  * dynamic types.
12243  */
12244 static void
12245 ensure_complete_type (MonoClass *klass)
12246 {
12247         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12248                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12249
12250                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12251
12252                 // Asserting here could break a lot of code
12253                 //g_assert (klass->wastypebuilder);
12254         }
12255
12256         if (klass->generic_class) {
12257                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12258                 int i;
12259
12260                 for (i = 0; i < inst->type_argc; ++i) {
12261                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12262                 }
12263         }
12264 }
12265
12266 static gpointer
12267 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12268 {
12269         gpointer result = NULL;
12270
12271         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12272                 result = mono_string_intern ((MonoString*)obj);
12273                 *handle_class = mono_defaults.string_class;
12274                 g_assert (result);
12275         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12276                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12277                 MonoClass *mc = mono_class_from_mono_type (type);
12278                 if (!mono_class_init (mc))
12279                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12280
12281                 if (context) {
12282                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12283                         result = mono_class_from_mono_type (inflated);
12284                         mono_metadata_free_type (inflated);
12285                 } else {
12286                         result = mono_class_from_mono_type (type);
12287                 }
12288                 *handle_class = mono_defaults.typehandle_class;
12289                 g_assert (result);
12290         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12291                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12292                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12293                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12294                 result = ((MonoReflectionMethod*)obj)->method;
12295                 if (context) {
12296                         MonoError error;
12297                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12298                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12299                 }
12300                 *handle_class = mono_defaults.methodhandle_class;
12301                 g_assert (result);
12302         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12303                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12304                 result = mb->mhandle;
12305                 if (!result) {
12306                         /* Type is not yet created */
12307                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12308
12309                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12310
12311                         /*
12312                          * Hopefully this has been filled in by calling CreateType() on the
12313                          * TypeBuilder.
12314                          */
12315                         /*
12316                          * TODO: This won't work if the application finishes another 
12317                          * TypeBuilder instance instead of this one.
12318                          */
12319                         result = mb->mhandle;
12320                 }
12321                 if (context) {
12322                         MonoError error;
12323                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12324                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12325                 }
12326                 *handle_class = mono_defaults.methodhandle_class;
12327         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12328                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12329
12330                 result = cb->mhandle;
12331                 if (!result) {
12332                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12333
12334                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12335                         result = cb->mhandle;
12336                 }
12337                 if (context) {
12338                         MonoError error;
12339                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12340                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12341                 }
12342                 *handle_class = mono_defaults.methodhandle_class;
12343         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12344                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12345
12346                 ensure_complete_type (field->parent);
12347                 if (context) {
12348                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12349                         MonoClass *klass = mono_class_from_mono_type (inflated);
12350                         MonoClassField *inflated_field;
12351                         gpointer iter = NULL;
12352                         mono_metadata_free_type (inflated);
12353                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12354                                 if (!strcmp (field->name, inflated_field->name))
12355                                         break;
12356                         }
12357                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12358                         result = inflated_field;
12359                 } else {
12360                         result = field;
12361                 }
12362                 *handle_class = mono_defaults.fieldhandle_class;
12363                 g_assert (result);
12364         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12365                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12366                 result = fb->handle;
12367
12368                 if (!result) {
12369                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12370
12371                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12372                         result = fb->handle;
12373                 }
12374
12375                 if (fb->handle && fb->handle->parent->generic_container) {
12376                         MonoClass *klass = fb->handle->parent;
12377                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12378                         MonoClass *inflated = mono_class_from_mono_type (type);
12379
12380                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12381                         g_assert (result);
12382                         mono_metadata_free_type (type);
12383                 }
12384                 *handle_class = mono_defaults.fieldhandle_class;
12385         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12386                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12387                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12388                 MonoClass *klass;
12389
12390                 klass = type->data.klass;
12391                 if (klass->wastypebuilder) {
12392                         /* Already created */
12393                         result = klass;
12394                 }
12395                 else {
12396                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12397                         result = type->data.klass;
12398                         g_assert (result);
12399                 }
12400                 *handle_class = mono_defaults.typehandle_class;
12401         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12402                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12403                 MonoMethodSignature *sig;
12404                 int nargs, i;
12405
12406                 if (helper->arguments)
12407                         nargs = mono_array_length (helper->arguments);
12408                 else
12409                         nargs = 0;
12410
12411                 sig = mono_metadata_signature_alloc (image, nargs);
12412                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12413                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12414
12415                 if (helper->unmanaged_call_conv) { /* unmanaged */
12416                         sig->call_convention = helper->unmanaged_call_conv - 1;
12417                         sig->pinvoke = TRUE;
12418                 } else if (helper->call_conv & 0x02) {
12419                         sig->call_convention = MONO_CALL_VARARG;
12420                 } else {
12421                         sig->call_convention = MONO_CALL_DEFAULT;
12422                 }
12423
12424                 sig->param_count = nargs;
12425                 /* TODO: Copy type ? */
12426                 sig->ret = helper->return_type->type;
12427                 for (i = 0; i < nargs; ++i)
12428                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12429
12430                 result = sig;
12431                 *handle_class = NULL;
12432         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12433                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12434                 /* Already created by the managed code */
12435                 g_assert (method->mhandle);
12436                 result = method->mhandle;
12437                 *handle_class = mono_defaults.methodhandle_class;
12438         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12439                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12440                 type = mono_class_inflate_generic_type (type, context);
12441                 result = mono_class_from_mono_type (type);
12442                 *handle_class = mono_defaults.typehandle_class;
12443                 g_assert (result);
12444                 mono_metadata_free_type (type);
12445         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12446                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12447                 type = mono_class_inflate_generic_type (type, context);
12448                 result = mono_class_from_mono_type (type);
12449                 *handle_class = mono_defaults.typehandle_class;
12450                 g_assert (result);
12451                 mono_metadata_free_type (type);
12452         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12453                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12454                 MonoClass *inflated;
12455                 MonoType *type;
12456                 MonoClassField *field;
12457
12458                 if (is_sre_field_builder (mono_object_class (f->fb)))
12459                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12460                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12461                         field = ((MonoReflectionField*)f->fb)->field;
12462                 else
12463                         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)));
12464
12465                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12466                 inflated = mono_class_from_mono_type (type);
12467
12468                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12469                 ensure_complete_type (field->parent);
12470                 g_assert (result);
12471                 mono_metadata_free_type (type);
12472                 *handle_class = mono_defaults.fieldhandle_class;
12473         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12474                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12475                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12476                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12477                 MonoMethod *method;
12478
12479                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12480                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12481                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12482                         method = ((MonoReflectionMethod *)c->cb)->method;
12483                 else
12484                         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)));
12485
12486                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12487                 *handle_class = mono_defaults.methodhandle_class;
12488                 mono_metadata_free_type (type);
12489         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12490                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12491                 if (m->method_args) {
12492                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12493                         if (context) {
12494                                 MonoError error;
12495                                 result = mono_class_inflate_generic_method_checked (result, context, &error);
12496                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12497                         }
12498                 } else {
12499                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12500                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12501                         MonoMethod *method;
12502
12503                         if (is_sre_method_builder (mono_object_class (m->mb)))
12504                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12505                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12506                                 method = ((MonoReflectionMethod *)m->mb)->method;
12507                         else
12508                                 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)));
12509
12510                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12511                         mono_metadata_free_type (type);
12512                 }
12513                 *handle_class = mono_defaults.methodhandle_class;
12514         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12515                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12516                 MonoType *mtype;
12517                 MonoClass *klass;
12518                 MonoMethod *method;
12519                 gpointer iter;
12520                 char *name;
12521
12522                 mtype = mono_reflection_type_get_handle (m->parent);
12523                 klass = mono_class_from_mono_type (mtype);
12524
12525                 /* Find the method */
12526
12527                 name = mono_string_to_utf8 (m->name);
12528                 iter = NULL;
12529                 while ((method = mono_class_get_methods (klass, &iter))) {
12530                         if (!strcmp (method->name, name))
12531                                 break;
12532                 }
12533                 g_free (name);
12534
12535                 // FIXME:
12536                 g_assert (method);
12537                 // FIXME: Check parameters/return value etc. match
12538
12539                 result = method;
12540                 *handle_class = mono_defaults.methodhandle_class;
12541         } else if (is_sre_array (mono_object_get_class(obj)) ||
12542                                 is_sre_byref (mono_object_get_class(obj)) ||
12543                                 is_sre_pointer (mono_object_get_class(obj))) {
12544                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12545                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12546
12547                 if (context) {
12548                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12549                         result = mono_class_from_mono_type (inflated);
12550                         mono_metadata_free_type (inflated);
12551                 } else {
12552                         result = mono_class_from_mono_type (type);
12553                 }
12554                 *handle_class = mono_defaults.typehandle_class;
12555         } else {
12556                 g_print ("%s\n", obj->vtable->klass->name);
12557                 g_assert_not_reached ();
12558         }
12559         return result;
12560 }
12561
12562 #else /* DISABLE_REFLECTION_EMIT */
12563
12564 MonoArray*
12565 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12566 {
12567         g_assert_not_reached ();
12568         return NULL;
12569 }
12570
12571 void
12572 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12573 {
12574         g_assert_not_reached ();
12575 }
12576
12577 void
12578 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12579 {
12580         g_assert_not_reached ();
12581 }
12582
12583 void
12584 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12585 {
12586         g_assert_not_reached ();
12587 }
12588
12589 void
12590 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12591 {
12592         g_assert_not_reached ();
12593 }
12594
12595 void
12596 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12597 {
12598         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12599 }
12600
12601 void
12602 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12603 {
12604         g_assert_not_reached ();
12605 }
12606
12607 void
12608 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12609 {
12610         g_assert_not_reached ();
12611 }
12612
12613 MonoReflectionModule *
12614 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12615 {
12616         g_assert_not_reached ();
12617         return NULL;
12618 }
12619
12620 guint32
12621 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12622 {
12623         g_assert_not_reached ();
12624         return 0;
12625 }
12626
12627 guint32
12628 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12629 {
12630         g_assert_not_reached ();
12631         return 0;
12632 }
12633
12634 guint32
12635 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12636                                                  gboolean create_open_instance, gboolean register_token)
12637 {
12638         g_assert_not_reached ();
12639         return 0;
12640 }
12641
12642 void
12643 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12644 {
12645 }
12646
12647 void
12648 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12649 {
12650         g_assert_not_reached ();
12651 }
12652
12653 void
12654 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12655 {
12656         *overrides = NULL;
12657         *num_overrides = 0;
12658 }
12659
12660 MonoReflectionEvent *
12661 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12662 {
12663         g_assert_not_reached ();
12664         return NULL;
12665 }
12666
12667 MonoReflectionType*
12668 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12669 {
12670         g_assert_not_reached ();
12671         return NULL;
12672 }
12673
12674 void
12675 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12676 {
12677         g_assert_not_reached ();
12678 }
12679
12680 MonoArray *
12681 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12682 {
12683         g_assert_not_reached ();
12684         return NULL;
12685 }
12686
12687 MonoArray *
12688 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12689 {
12690         g_assert_not_reached ();
12691         return NULL;
12692 }
12693
12694 void 
12695 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12696 {
12697 }
12698
12699 gpointer
12700 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12701 {
12702         return NULL;
12703 }
12704
12705 MonoType*
12706 mono_reflection_type_get_handle (MonoReflectionType* ref)
12707 {
12708         if (!ref)
12709                 return NULL;
12710         return ref->type;
12711 }
12712
12713 void
12714 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12715 {
12716         g_assert_not_reached ();
12717 }
12718
12719 #endif /* DISABLE_REFLECTION_EMIT */
12720
12721 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12722 const static guint32 declsec_flags_map[] = {
12723         0x00000000,                                     /* empty */
12724         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12725         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12726         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12727         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12728         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12729         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12730         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12731         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12732         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12733         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12734         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12735         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12736         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12737         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12738         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12739         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12740         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12741         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12742 };
12743
12744 /*
12745  * Returns flags that includes all available security action associated to the handle.
12746  * @token: metadata token (either for a class or a method)
12747  * @image: image where resides the metadata.
12748  */
12749 static guint32
12750 mono_declsec_get_flags (MonoImage *image, guint32 token)
12751 {
12752         int index = mono_metadata_declsec_from_index (image, token);
12753         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12754         guint32 result = 0;
12755         guint32 action;
12756         int i;
12757
12758         /* HasSecurity can be present for other, not specially encoded, attributes,
12759            e.g. SuppressUnmanagedCodeSecurityAttribute */
12760         if (index < 0)
12761                 return 0;
12762
12763         for (i = index; i < t->rows; i++) {
12764                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12765
12766                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12767                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12768                         break;
12769
12770                 action = cols [MONO_DECL_SECURITY_ACTION];
12771                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12772                         result |= declsec_flags_map [action];
12773                 } else {
12774                         g_assert_not_reached ();
12775                 }
12776         }
12777         return result;
12778 }
12779
12780 /*
12781  * Get the security actions (in the form of flags) associated with the specified method.
12782  *
12783  * @method: The method for which we want the declarative security flags.
12784  * Return the declarative security flags for the method (only).
12785  *
12786  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12787  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12788  */
12789 guint32
12790 mono_declsec_flags_from_method (MonoMethod *method)
12791 {
12792         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12793                 /* FIXME: No cache (for the moment) */
12794                 guint32 idx = mono_method_get_index (method);
12795                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12796                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12797                 return mono_declsec_get_flags (method->klass->image, idx);
12798         }
12799         return 0;
12800 }
12801
12802 /*
12803  * Get the security actions (in the form of flags) associated with the specified class.
12804  *
12805  * @klass: The class for which we want the declarative security flags.
12806  * Return the declarative security flags for the class.
12807  *
12808  * Note: We cache the flags inside the MonoClass structure as this will get 
12809  *       called very often (at least for each method).
12810  */
12811 guint32
12812 mono_declsec_flags_from_class (MonoClass *klass)
12813 {
12814         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12815                 if (!klass->ext || !klass->ext->declsec_flags) {
12816                         guint32 idx;
12817
12818                         idx = mono_metadata_token_index (klass->type_token);
12819                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12820                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12821                         mono_loader_lock ();
12822                         mono_class_alloc_ext (klass);
12823                         mono_loader_unlock ();
12824                         /* we cache the flags on classes */
12825                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12826                 }
12827                 return klass->ext->declsec_flags;
12828         }
12829         return 0;
12830 }
12831
12832 /*
12833  * Get the security actions (in the form of flags) associated with the specified assembly.
12834  *
12835  * @assembly: The assembly for which we want the declarative security flags.
12836  * Return the declarative security flags for the assembly.
12837  */
12838 guint32
12839 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12840 {
12841         guint32 idx = 1; /* there is only one assembly */
12842         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12843         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12844         return mono_declsec_get_flags (assembly->image, idx);
12845 }
12846
12847
12848 /*
12849  * Fill actions for the specific index (which may either be an encoded class token or
12850  * an encoded method token) from the metadata image.
12851  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12852  */
12853 static MonoBoolean
12854 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12855         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12856 {
12857         MonoBoolean result = FALSE;
12858         MonoTableInfo *t;
12859         guint32 cols [MONO_DECL_SECURITY_SIZE];
12860         int index = mono_metadata_declsec_from_index (image, token);
12861         int i;
12862
12863         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12864         for (i = index; i < t->rows; i++) {
12865                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12866
12867                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12868                         return result;
12869
12870                 /* if present only replace (class) permissions with method permissions */
12871                 /* if empty accept either class or method permissions */
12872                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12873                         if (!actions->demand.blob) {
12874                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12875                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12876                                 actions->demand.blob = (char*) (blob + 2);
12877                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12878                                 result = TRUE;
12879                         }
12880                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12881                         if (!actions->noncasdemand.blob) {
12882                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12883                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12884                                 actions->noncasdemand.blob = (char*) (blob + 2);
12885                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12886                                 result = TRUE;
12887                         }
12888                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12889                         if (!actions->demandchoice.blob) {
12890                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12891                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12892                                 actions->demandchoice.blob = (char*) (blob + 2);
12893                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12894                                 result = TRUE;
12895                         }
12896                 }
12897         }
12898
12899         return result;
12900 }
12901
12902 static MonoBoolean
12903 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12904         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12905 {
12906         guint32 idx = mono_metadata_token_index (klass->type_token);
12907         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12908         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12909         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12910 }
12911
12912 static MonoBoolean
12913 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12914         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12915 {
12916         guint32 idx = mono_method_get_index (method);
12917         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12918         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12919         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12920 }
12921
12922 /*
12923  * Collect all actions (that requires to generate code in mini) assigned for
12924  * the specified method.
12925  * Note: Don't use the content of actions if the function return FALSE.
12926  */
12927 MonoBoolean
12928 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12929 {
12930         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12931                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12932         MonoBoolean result = FALSE;
12933         guint32 flags;
12934
12935         /* quick exit if no declarative security is present in the metadata */
12936         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12937                 return FALSE;
12938
12939         /* we want the original as the wrapper is "free" of the security informations */
12940         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12941                 method = mono_marshal_method_from_wrapper (method);
12942                 if (!method)
12943                         return FALSE;
12944         }
12945
12946         /* First we look for method-level attributes */
12947         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12948                 mono_class_init (method->klass);
12949                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12950
12951                 result = mono_declsec_get_method_demands_params (method, demands, 
12952                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12953         }
12954
12955         /* Here we use (or create) the class declarative cache to look for demands */
12956         flags = mono_declsec_flags_from_class (method->klass);
12957         if (flags & mask) {
12958                 if (!result) {
12959                         mono_class_init (method->klass);
12960                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12961                 }
12962                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12963                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12964         }
12965
12966         /* The boolean return value is used as a shortcut in case nothing needs to
12967            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12968         return result;
12969 }
12970
12971
12972 /*
12973  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12974  *
12975  * Note: Don't use the content of actions if the function return FALSE.
12976  */
12977 MonoBoolean
12978 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12979 {
12980         MonoBoolean result = FALSE;
12981         guint32 flags;
12982
12983         /* quick exit if no declarative security is present in the metadata */
12984         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12985                 return FALSE;
12986
12987         /* we want the original as the wrapper is "free" of the security informations */
12988         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12989                 method = mono_marshal_method_from_wrapper (method);
12990                 if (!method)
12991                         return FALSE;
12992         }
12993
12994         /* results are independant - zeroize both */
12995         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12996         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12997
12998         /* First we look for method-level attributes */
12999         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13000                 mono_class_init (method->klass);
13001
13002                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13003                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13004         }
13005
13006         /* Here we use (or create) the class declarative cache to look for demands */
13007         flags = mono_declsec_flags_from_class (method->klass);
13008         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13009                 mono_class_init (method->klass);
13010
13011                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13012                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13013         }
13014
13015         return result;
13016 }
13017
13018 /*
13019  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13020  *
13021  * @klass       The inherited class - this is the class that provides the security check (attributes)
13022  * @demans      
13023  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13024  * 
13025  * Note: Don't use the content of actions if the function return FALSE.
13026  */
13027 MonoBoolean
13028 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13029 {
13030         MonoBoolean result = FALSE;
13031         guint32 flags;
13032
13033         /* quick exit if no declarative security is present in the metadata */
13034         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13035                 return FALSE;
13036
13037         /* Here we use (or create) the class declarative cache to look for demands */
13038         flags = mono_declsec_flags_from_class (klass);
13039         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13040                 mono_class_init (klass);
13041                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13042
13043                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13044                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13045         }
13046
13047         return result;
13048 }
13049
13050 /*
13051  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13052  *
13053  * Note: Don't use the content of actions if the function return FALSE.
13054  */
13055 MonoBoolean
13056 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13057 {
13058         /* quick exit if no declarative security is present in the metadata */
13059         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13060                 return FALSE;
13061
13062         /* we want the original as the wrapper is "free" of the security informations */
13063         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13064                 method = mono_marshal_method_from_wrapper (method);
13065                 if (!method)
13066                         return FALSE;
13067         }
13068
13069         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13070                 mono_class_init (method->klass);
13071                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13072
13073                 return mono_declsec_get_method_demands_params (method, demands, 
13074                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13075         }
13076         return FALSE;
13077 }
13078
13079
13080 static MonoBoolean
13081 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13082 {
13083         guint32 cols [MONO_DECL_SECURITY_SIZE];
13084         MonoTableInfo *t;
13085         int i;
13086
13087         int index = mono_metadata_declsec_from_index (image, token);
13088         if (index == -1)
13089                 return FALSE;
13090
13091         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13092         for (i = index; i < t->rows; i++) {
13093                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13094
13095                 /* shortcut - index are ordered */
13096                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13097                         return FALSE;
13098
13099                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13100                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13101                         entry->blob = (char*) (metadata + 2);
13102                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13103                         return TRUE;
13104                 }
13105         }
13106
13107         return FALSE;
13108 }
13109
13110 MonoBoolean
13111 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13112 {
13113         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13114                 guint32 idx = mono_method_get_index (method);
13115                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13116                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13117                 return get_declsec_action (method->klass->image, idx, action, entry);
13118         }
13119         return FALSE;
13120 }
13121
13122 MonoBoolean
13123 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13124 {
13125         /* use cache */
13126         guint32 flags = mono_declsec_flags_from_class (klass);
13127         if (declsec_flags_map [action] & flags) {
13128                 guint32 idx = mono_metadata_token_index (klass->type_token);
13129                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13130                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13131                 return get_declsec_action (klass->image, idx, action, entry);
13132         }
13133         return FALSE;
13134 }
13135
13136 MonoBoolean
13137 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13138 {
13139         guint32 idx = 1; /* there is only one assembly */
13140         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13141         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13142
13143         return get_declsec_action (assembly->image, idx, action, entry);
13144 }
13145
13146 gboolean
13147 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13148 {
13149         MonoObject *res, *exc;
13150         void *params [1];
13151         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13152         static MonoMethod *method = NULL;
13153
13154         if (!System_Reflection_Emit_TypeBuilder) {
13155                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13156                 g_assert (System_Reflection_Emit_TypeBuilder);
13157         }
13158         if (method == NULL) {
13159                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13160                 g_assert (method);
13161         }
13162
13163         /* 
13164          * The result of mono_type_get_object () might be a System.MonoType but we
13165          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13166          */
13167         g_assert (mono_class_get_ref_info (klass));
13168         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13169
13170         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13171
13172         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13173         if (exc)
13174                 return FALSE;
13175         else
13176                 return *(MonoBoolean*)mono_object_unbox (res);
13177 }
13178
13179 /**
13180  * mono_reflection_type_get_type:
13181  * @reftype: the System.Type object
13182  *
13183  * Returns the MonoType* associated with the C# System.Type object @reftype.
13184  */
13185 MonoType*
13186 mono_reflection_type_get_type (MonoReflectionType *reftype)
13187 {
13188         g_assert (reftype);
13189
13190         return mono_reflection_type_get_handle (reftype);
13191 }
13192
13193 /**
13194  * mono_reflection_assembly_get_assembly:
13195  * @refassembly: the System.Reflection.Assembly object
13196  *
13197  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13198  */
13199 MonoAssembly*
13200 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13201 {
13202         g_assert (refassembly);
13203
13204         return refassembly->assembly;
13205 }
13206