Merge pull request #2516 from lambdageek/monoerror-exception_instance
[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 = (MonoObject *)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_os_mutex_lock (&dynamic_images_mutex);
226 }
227
228 static inline void
229 dynamic_images_unlock (void)
230 {
231         mono_os_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 = (MonoImage *)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         mono_os_mutex_init (&dynamic_images_mutex);
265 }
266
267 static inline void
268 dynamic_image_lock (MonoDynamicImage *image)
269 {
270         MONO_PREPARE_BLOCKING;
271         mono_image_lock ((MonoImage*)image);
272         MONO_FINISH_BLOCKING;
273 }
274
275 static inline void
276 dynamic_image_unlock (MonoDynamicImage *image)
277 {
278         mono_image_unlock ((MonoImage*)image);
279 }
280
281 static void
282 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
283 {
284         MONO_REQ_GC_UNSAFE_MODE;
285
286         dynamic_image_lock (assembly);
287         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
288         dynamic_image_unlock (assembly);
289 }
290
291 static MonoObject*
292 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
293 {
294         MONO_REQ_GC_UNSAFE_MODE;
295
296         MonoObject *obj;
297
298         dynamic_image_lock (assembly);
299         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
300         dynamic_image_unlock (assembly);
301
302         return obj;
303 }
304
305 static void
306 sigbuffer_init (SigBuffer *buf, int size)
307 {
308         MONO_REQ_GC_NEUTRAL_MODE;
309
310         buf->buf = (char *)g_malloc (size);
311         buf->p = buf->buf;
312         buf->end = buf->buf + size;
313 }
314
315 static void
316 sigbuffer_make_room (SigBuffer *buf, int size)
317 {
318         MONO_REQ_GC_NEUTRAL_MODE;
319
320         if (buf->end - buf->p < size) {
321                 int new_size = buf->end - buf->buf + size + 32;
322                 char *p = (char *)g_realloc (buf->buf, new_size);
323                 size = buf->p - buf->buf;
324                 buf->buf = p;
325                 buf->p = p + size;
326                 buf->end = buf->buf + new_size;
327         }
328 }
329
330 static void
331 sigbuffer_add_value (SigBuffer *buf, guint32 val)
332 {
333         MONO_REQ_GC_NEUTRAL_MODE;
334
335         sigbuffer_make_room (buf, 6);
336         mono_metadata_encode_value (val, buf->p, &buf->p);
337 }
338
339 static void
340 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         sigbuffer_make_room (buf, 1);
345         buf->p [0] = val;
346         buf->p++;
347 }
348
349 static void
350 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
351 {
352         MONO_REQ_GC_NEUTRAL_MODE;
353
354         sigbuffer_make_room (buf, size);
355         memcpy (buf->p, p, size);
356         buf->p += size;
357 }
358
359 static void
360 sigbuffer_free (SigBuffer *buf)
361 {
362         MONO_REQ_GC_NEUTRAL_MODE;
363
364         g_free (buf->buf);
365 }
366
367 #ifndef DISABLE_REFLECTION_EMIT
368 /**
369  * mp_g_alloc:
370  *
371  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
372  * from the C heap.
373  */
374 static gpointer
375 image_g_malloc (MonoImage *image, guint size)
376 {
377         MONO_REQ_GC_NEUTRAL_MODE;
378
379         if (image)
380                 return mono_image_alloc (image, size);
381         else
382                 return g_malloc (size);
383 }
384 #endif /* !DISABLE_REFLECTION_EMIT */
385
386 /**
387  * image_g_alloc0:
388  *
389  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
390  * from the C heap.
391  */
392 static gpointer
393 image_g_malloc0 (MonoImage *image, guint size)
394 {
395         MONO_REQ_GC_NEUTRAL_MODE;
396
397         if (image)
398                 return mono_image_alloc0 (image, size);
399         else
400                 return g_malloc0 (size);
401 }
402
403 #ifndef DISABLE_REFLECTION_EMIT
404 static char*
405 image_strdup (MonoImage *image, const char *s)
406 {
407         MONO_REQ_GC_NEUTRAL_MODE;
408
409         if (image)
410                 return mono_image_strdup (image, s);
411         else
412                 return g_strdup (s);
413 }
414 #endif
415
416 #define image_g_new(image,struct_type, n_structs)               \
417     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
418
419 #define image_g_new0(image,struct_type, n_structs)              \
420     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
421
422
423 static void
424 alloc_table (MonoDynamicTable *table, guint nrows)
425 {
426         MONO_REQ_GC_NEUTRAL_MODE;
427
428         table->rows = nrows;
429         g_assert (table->columns);
430         if (nrows + 1 >= table->alloc_rows) {
431                 while (nrows + 1 >= table->alloc_rows) {
432                         if (table->alloc_rows == 0)
433                                 table->alloc_rows = 16;
434                         else
435                                 table->alloc_rows *= 2;
436                 }
437
438                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
439         }
440 }
441
442 static void
443 make_room_in_stream (MonoDynamicStream *stream, int size)
444 {
445         MONO_REQ_GC_NEUTRAL_MODE;
446
447         if (size <= stream->alloc_size)
448                 return;
449         
450         while (stream->alloc_size <= size) {
451                 if (stream->alloc_size < 4096)
452                         stream->alloc_size = 4096;
453                 else
454                         stream->alloc_size *= 2;
455         }
456         
457         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
458 }
459
460 static guint32
461 string_heap_insert (MonoDynamicStream *sh, const char *str)
462 {
463         MONO_REQ_GC_NEUTRAL_MODE;
464
465         guint32 idx;
466         guint32 len;
467         gpointer oldkey, oldval;
468
469         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
470                 return GPOINTER_TO_UINT (oldval);
471
472         len = strlen (str) + 1;
473         idx = sh->index;
474         
475         make_room_in_stream (sh, idx + len);
476
477         /*
478          * We strdup the string even if we already copy them in sh->data
479          * so that the string pointers in the hash remain valid even if
480          * we need to realloc sh->data. We may want to avoid that later.
481          */
482         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
483         memcpy (sh->data + idx, str, len);
484         sh->index += len;
485         return idx;
486 }
487
488 static guint32
489 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
490 {
491         MONO_REQ_GC_UNSAFE_MODE;
492
493         char *name = mono_string_to_utf8 (str);
494         guint32 idx;
495         idx = string_heap_insert (sh, name);
496         g_free (name);
497         return idx;
498 }
499
500 #ifndef DISABLE_REFLECTION_EMIT
501 static void
502 string_heap_init (MonoDynamicStream *sh)
503 {
504         MONO_REQ_GC_NEUTRAL_MODE;
505
506         sh->index = 0;
507         sh->alloc_size = 4096;
508         sh->data = (char *)g_malloc (4096);
509         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
510         string_heap_insert (sh, "");
511 }
512 #endif
513
514 static guint32
515 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
516 {
517         MONO_REQ_GC_NEUTRAL_MODE;
518
519         guint32 idx;
520         
521         make_room_in_stream (stream, stream->index + len);
522         memcpy (stream->data + stream->index, data, len);
523         idx = stream->index;
524         stream->index += len;
525         /* 
526          * align index? Not without adding an additional param that controls it since
527          * we may store a blob value in pieces.
528          */
529         return idx;
530 }
531
532 static guint32
533 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
534 {
535         MONO_REQ_GC_NEUTRAL_MODE;
536
537         guint32 idx;
538         
539         make_room_in_stream (stream, stream->index + len);
540         memset (stream->data + stream->index, 0, len);
541         idx = stream->index;
542         stream->index += len;
543         return idx;
544 }
545
546 static void
547 stream_data_align (MonoDynamicStream *stream)
548 {
549         MONO_REQ_GC_NEUTRAL_MODE;
550
551         char buf [4] = {0};
552         guint32 count = stream->index % 4;
553
554         /* we assume the stream data will be aligned */
555         if (count)
556                 mono_image_add_stream_data (stream, buf, 4 - count);
557 }
558
559 #ifndef DISABLE_REFLECTION_EMIT
560 static int
561 mono_blob_entry_hash (const char* str)
562 {
563         MONO_REQ_GC_NEUTRAL_MODE;
564
565         guint len, h;
566         const char *end;
567         len = mono_metadata_decode_blob_size (str, &str);
568         if (len > 0) {
569                 end = str + len;
570                 h = *str;
571                 for (str += 1; str < end; str++)
572                         h = (h << 5) - h + *str;
573                 return h;
574         } else {
575                 return 0;
576         }
577 }
578
579 static gboolean
580 mono_blob_entry_equal (const char *str1, const char *str2) {
581         MONO_REQ_GC_NEUTRAL_MODE;
582
583         int len, len2;
584         const char *end1;
585         const char *end2;
586         len = mono_metadata_decode_blob_size (str1, &end1);
587         len2 = mono_metadata_decode_blob_size (str2, &end2);
588         if (len != len2)
589                 return 0;
590         return memcmp (end1, end2, len) == 0;
591 }
592 #endif
593 static guint32
594 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
595 {
596         MONO_REQ_GC_NEUTRAL_MODE;
597
598         guint32 idx;
599         char *copy;
600         gpointer oldkey, oldval;
601
602         copy = (char *)g_malloc (s1+s2);
603         memcpy (copy, b1, s1);
604         memcpy (copy + s1, b2, s2);
605         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
606                 g_free (copy);
607                 idx = GPOINTER_TO_UINT (oldval);
608         } else {
609                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
610                 mono_image_add_stream_data (&assembly->blob, b2, s2);
611                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
612         }
613         return idx;
614 }
615
616 static guint32
617 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
618 {
619         MONO_REQ_GC_NEUTRAL_MODE;
620
621         char blob_size [8];
622         char *b = blob_size;
623         guint32 size = buf->p - buf->buf;
624         /* store length */
625         g_assert (size <= (buf->end - buf->buf));
626         mono_metadata_encode_value (size, b, &b);
627         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
628 }
629
630 /*
631  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
632  * dest may be misaligned.
633  */
634 static void
635 swap_with_size (char *dest, const char* val, int len, int nelem) {
636         MONO_REQ_GC_NEUTRAL_MODE;
637 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
638         int elem;
639
640         for (elem = 0; elem < nelem; ++elem) {
641                 switch (len) {
642                 case 1:
643                         *dest = *val;
644                         break;
645                 case 2:
646                         dest [0] = val [1];
647                         dest [1] = val [0];
648                         break;
649                 case 4:
650                         dest [0] = val [3];
651                         dest [1] = val [2];
652                         dest [2] = val [1];
653                         dest [3] = val [0];
654                         break;
655                 case 8:
656                         dest [0] = val [7];
657                         dest [1] = val [6];
658                         dest [2] = val [5];
659                         dest [3] = val [4];
660                         dest [4] = val [3];
661                         dest [5] = val [2];
662                         dest [6] = val [1];
663                         dest [7] = val [0];
664                         break;
665                 default:
666                         g_assert_not_reached ();
667                 }
668                 dest += len;
669                 val += len;
670         }
671 #else
672         memcpy (dest, val, len * nelem);
673 #endif
674 }
675
676 static guint32
677 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
678 {
679         MONO_REQ_GC_UNSAFE_MODE;
680         
681         char blob_size [64];
682         char *b = blob_size;
683         guint32 idx = 0, len;
684
685         len = str->length * 2;
686         mono_metadata_encode_value (len, b, &b);
687 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
688         {
689                 char *swapped = g_malloc (2 * mono_string_length (str));
690                 const char *p = (const char*)mono_string_chars (str);
691
692                 swap_with_size (swapped, p, 2, mono_string_length (str));
693                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
694                 g_free (swapped);
695         }
696 #else
697         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
698 #endif
699         return idx;
700 }
701
702 #ifndef DISABLE_REFLECTION_EMIT
703 static MonoClass *
704 default_class_from_mono_type (MonoType *type)
705 {
706         MONO_REQ_GC_NEUTRAL_MODE;
707
708         switch (type->type) {
709         case MONO_TYPE_OBJECT:
710                 return mono_defaults.object_class;
711         case MONO_TYPE_VOID:
712                 return mono_defaults.void_class;
713         case MONO_TYPE_BOOLEAN:
714                 return mono_defaults.boolean_class;
715         case MONO_TYPE_CHAR:
716                 return mono_defaults.char_class;
717         case MONO_TYPE_I1:
718                 return mono_defaults.sbyte_class;
719         case MONO_TYPE_U1:
720                 return mono_defaults.byte_class;
721         case MONO_TYPE_I2:
722                 return mono_defaults.int16_class;
723         case MONO_TYPE_U2:
724                 return mono_defaults.uint16_class;
725         case MONO_TYPE_I4:
726                 return mono_defaults.int32_class;
727         case MONO_TYPE_U4:
728                 return mono_defaults.uint32_class;
729         case MONO_TYPE_I:
730                 return mono_defaults.int_class;
731         case MONO_TYPE_U:
732                 return mono_defaults.uint_class;
733         case MONO_TYPE_I8:
734                 return mono_defaults.int64_class;
735         case MONO_TYPE_U8:
736                 return mono_defaults.uint64_class;
737         case MONO_TYPE_R4:
738                 return mono_defaults.single_class;
739         case MONO_TYPE_R8:
740                 return mono_defaults.double_class;
741         case MONO_TYPE_STRING:
742                 return mono_defaults.string_class;
743         default:
744                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
745                 g_assert_not_reached ();
746         }
747         
748         return NULL;
749 }
750 #endif
751
752 /*
753  * mono_class_get_ref_info:
754  *
755  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
756  */
757 gpointer
758 mono_class_get_ref_info (MonoClass *klass)
759 {
760         MONO_REQ_GC_UNSAFE_MODE;
761
762         if (klass->ref_info_handle == 0)
763                 return NULL;
764         else
765                 return mono_gchandle_get_target (klass->ref_info_handle);
766 }
767
768 void
769 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
770 {
771         MONO_REQ_GC_UNSAFE_MODE;
772
773         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
774         g_assert (klass->ref_info_handle != 0);
775 }
776
777 void
778 mono_class_free_ref_info (MonoClass *klass)
779 {
780         MONO_REQ_GC_NEUTRAL_MODE;
781
782         if (klass->ref_info_handle) {
783                 mono_gchandle_free (klass->ref_info_handle);
784                 klass->ref_info_handle = 0;
785         }
786 }
787
788 static void
789 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
790 {
791         MONO_REQ_GC_NEUTRAL_MODE;
792
793         int i;
794         MonoGenericInst *class_inst;
795         MonoClass *klass;
796
797         g_assert (gclass);
798
799         class_inst = gclass->context.class_inst;
800
801         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
802         klass = gclass->container_class;
803         sigbuffer_add_value (buf, klass->byval_arg.type);
804         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
805
806         sigbuffer_add_value (buf, class_inst->type_argc);
807         for (i = 0; i < class_inst->type_argc; ++i)
808                 encode_type (assembly, class_inst->type_argv [i], buf);
809
810 }
811
812 static void
813 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
814 {
815         MONO_REQ_GC_NEUTRAL_MODE;
816
817         if (!type) {
818                 g_assert_not_reached ();
819                 return;
820         }
821                 
822         if (type->byref)
823                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
824
825         switch (type->type){
826         case MONO_TYPE_VOID:
827         case MONO_TYPE_BOOLEAN:
828         case MONO_TYPE_CHAR:
829         case MONO_TYPE_I1:
830         case MONO_TYPE_U1:
831         case MONO_TYPE_I2:
832         case MONO_TYPE_U2:
833         case MONO_TYPE_I4:
834         case MONO_TYPE_U4:
835         case MONO_TYPE_I8:
836         case MONO_TYPE_U8:
837         case MONO_TYPE_R4:
838         case MONO_TYPE_R8:
839         case MONO_TYPE_I:
840         case MONO_TYPE_U:
841         case MONO_TYPE_STRING:
842         case MONO_TYPE_OBJECT:
843         case MONO_TYPE_TYPEDBYREF:
844                 sigbuffer_add_value (buf, type->type);
845                 break;
846         case MONO_TYPE_PTR:
847                 sigbuffer_add_value (buf, type->type);
848                 encode_type (assembly, type->data.type, buf);
849                 break;
850         case MONO_TYPE_SZARRAY:
851                 sigbuffer_add_value (buf, type->type);
852                 encode_type (assembly, &type->data.klass->byval_arg, buf);
853                 break;
854         case MONO_TYPE_VALUETYPE:
855         case MONO_TYPE_CLASS: {
856                 MonoClass *k = mono_class_from_mono_type (type);
857
858                 if (k->generic_container) {
859                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
860                         encode_generic_class (assembly, gclass, buf);
861                 } else {
862                         /*
863                          * Make sure we use the correct type.
864                          */
865                         sigbuffer_add_value (buf, k->byval_arg.type);
866                         /*
867                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
868                          * otherwise two typerefs could point to the same type, leading to
869                          * verification errors.
870                          */
871                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
872                 }
873                 break;
874         }
875         case MONO_TYPE_ARRAY:
876                 sigbuffer_add_value (buf, type->type);
877                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
878                 sigbuffer_add_value (buf, type->data.array->rank);
879                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
880                 sigbuffer_add_value (buf, 0);
881                 break;
882         case MONO_TYPE_GENERICINST:
883                 encode_generic_class (assembly, type->data.generic_class, buf);
884                 break;
885         case MONO_TYPE_VAR:
886         case MONO_TYPE_MVAR:
887                 sigbuffer_add_value (buf, type->type);
888                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
889                 break;
890         default:
891                 g_error ("need to encode type %x", type->type);
892         }
893 }
894
895 static void
896 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
897 {
898         MONO_REQ_GC_UNSAFE_MODE;
899
900         if (!type) {
901                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
902                 return;
903         }
904
905         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
906 }
907
908 static void
909 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
910 {
911         MONO_REQ_GC_UNSAFE_MODE;
912
913         int i;
914
915         if (modreq) {
916                 for (i = 0; i < mono_array_length (modreq); ++i) {
917                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
918                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
919                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
920                 }
921         }
922         if (modopt) {
923                 for (i = 0; i < mono_array_length (modopt); ++i) {
924                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
925                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
926                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
927                 }
928         }
929 }
930
931 #ifndef DISABLE_REFLECTION_EMIT
932 static guint32
933 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
934 {
935         MONO_REQ_GC_UNSAFE_MODE;
936
937         SigBuffer buf;
938         int i;
939         guint32 nparams =  sig->param_count;
940         guint32 idx;
941
942         if (!assembly->save)
943                 return 0;
944
945         sigbuffer_init (&buf, 32);
946         /*
947          * FIXME: vararg, explicit_this, differenc call_conv values...
948          */
949         idx = sig->call_convention;
950         if (sig->hasthis)
951                 idx |= 0x20; /* hasthis */
952         if (sig->generic_param_count)
953                 idx |= 0x10; /* generic */
954         sigbuffer_add_byte (&buf, idx);
955         if (sig->generic_param_count)
956                 sigbuffer_add_value (&buf, sig->generic_param_count);
957         sigbuffer_add_value (&buf, nparams);
958         encode_type (assembly, sig->ret, &buf);
959         for (i = 0; i < nparams; ++i) {
960                 if (i == sig->sentinelpos)
961                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
962                 encode_type (assembly, sig->params [i], &buf);
963         }
964         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
965         sigbuffer_free (&buf);
966         return idx;
967 }
968 #endif
969
970 static guint32
971 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
972 {
973         MONO_REQ_GC_UNSAFE_MODE;
974
975         /*
976          * FIXME: reuse code from method_encode_signature().
977          */
978         SigBuffer buf;
979         int i;
980         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
981         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
982         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
983         guint32 idx;
984
985         sigbuffer_init (&buf, 32);
986         /* LAMESPEC: all the call conv spec is foobared */
987         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
988         if (mb->call_conv & 2)
989                 idx |= 0x5; /* vararg */
990         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
991                 idx |= 0x20; /* hasthis */
992         if (ngparams)
993                 idx |= 0x10; /* generic */
994         sigbuffer_add_byte (&buf, idx);
995         if (ngparams)
996                 sigbuffer_add_value (&buf, ngparams);
997         sigbuffer_add_value (&buf, nparams + notypes);
998         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
999         encode_reflection_type (assembly, mb->rtype, &buf);
1000         for (i = 0; i < nparams; ++i) {
1001                 MonoArray *modreq = NULL;
1002                 MonoArray *modopt = NULL;
1003                 MonoReflectionType *pt;
1004
1005                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1006                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1007                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1008                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1009                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1010                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1011                 encode_reflection_type (assembly, pt, &buf);
1012         }
1013         if (notypes)
1014                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1015         for (i = 0; i < notypes; ++i) {
1016                 MonoReflectionType *pt;
1017
1018                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1019                 encode_reflection_type (assembly, pt, &buf);
1020         }
1021
1022         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1023         sigbuffer_free (&buf);
1024         return idx;
1025 }
1026
1027 static guint32
1028 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1029 {
1030         MONO_REQ_GC_UNSAFE_MODE;
1031
1032         MonoDynamicTable *table;
1033         guint32 *values;
1034         guint32 idx, sig_idx;
1035         guint nl = mono_array_length (ilgen->locals);
1036         SigBuffer buf;
1037         int i;
1038
1039         sigbuffer_init (&buf, 32);
1040         sigbuffer_add_value (&buf, 0x07);
1041         sigbuffer_add_value (&buf, nl);
1042         for (i = 0; i < nl; ++i) {
1043                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1044                 
1045                 if (lb->is_pinned)
1046                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1047                 
1048                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1049         }
1050         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1051         sigbuffer_free (&buf);
1052
1053         if (assembly->standalonesig_cache == NULL)
1054                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1055         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1056         if (idx)
1057                 return idx;
1058
1059         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1060         idx = table->next_idx ++;
1061         table->rows ++;
1062         alloc_table (table, table->rows);
1063         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1064
1065         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1066
1067         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1068
1069         return idx;
1070 }
1071
1072 static guint32
1073 method_count_clauses (MonoReflectionILGen *ilgen)
1074 {
1075         MONO_REQ_GC_UNSAFE_MODE;
1076
1077         guint32 num_clauses = 0;
1078         int i;
1079
1080         MonoILExceptionInfo *ex_info;
1081         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1082                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1083                 if (ex_info->handlers)
1084                         num_clauses += mono_array_length (ex_info->handlers);
1085                 else
1086                         num_clauses++;
1087         }
1088
1089         return num_clauses;
1090 }
1091
1092 #ifndef DISABLE_REFLECTION_EMIT
1093 static MonoExceptionClause*
1094 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1095 {
1096         MONO_REQ_GC_UNSAFE_MODE;
1097
1098         MonoExceptionClause *clauses;
1099         MonoExceptionClause *clause;
1100         MonoILExceptionInfo *ex_info;
1101         MonoILExceptionBlock *ex_block;
1102         guint32 finally_start;
1103         int i, j, clause_index;;
1104
1105         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1106
1107         clause_index = 0;
1108         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1109                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1110                 finally_start = ex_info->start + ex_info->len;
1111                 if (!ex_info->handlers)
1112                         continue;
1113                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1114                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1115                         clause = &(clauses [clause_index]);
1116
1117                         clause->flags = ex_block->type;
1118                         clause->try_offset = ex_info->start;
1119
1120                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1121                                 clause->try_len = finally_start - ex_info->start;
1122                         else
1123                                 clause->try_len = ex_info->len;
1124                         clause->handler_offset = ex_block->start;
1125                         clause->handler_len = ex_block->len;
1126                         if (ex_block->extype) {
1127                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1128                         } else {
1129                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1130                                         clause->data.filter_offset = ex_block->filter_offset;
1131                                 else
1132                                         clause->data.filter_offset = 0;
1133                         }
1134                         finally_start = ex_block->start + ex_block->len;
1135
1136                         clause_index ++;
1137                 }
1138         }
1139
1140         return clauses;
1141 }
1142 #endif /* !DISABLE_REFLECTION_EMIT */
1143
1144 static guint32
1145 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1146 {
1147         MONO_REQ_GC_UNSAFE_MODE;
1148
1149         char flags = 0;
1150         guint32 idx;
1151         guint32 code_size;
1152         gint32 max_stack, i;
1153         gint32 num_locals = 0;
1154         gint32 num_exception = 0;
1155         gint maybe_small;
1156         guint32 fat_flags;
1157         char fat_header [12];
1158         guint32 int_value;
1159         guint16 short_value;
1160         guint32 local_sig = 0;
1161         guint32 header_size = 12;
1162         MonoArray *code;
1163
1164         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1165                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1166                 return 0;
1167
1168         /*if (mb->name)
1169                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1170         if (mb->ilgen) {
1171                 code = mb->ilgen->code;
1172                 code_size = mb->ilgen->code_len;
1173                 max_stack = mb->ilgen->max_stack;
1174                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1175                 if (mb->ilgen->ex_handlers)
1176                         num_exception = method_count_clauses (mb->ilgen);
1177         } else {
1178                 code = mb->code;
1179                 if (code == NULL){
1180                         char *name = mono_string_to_utf8 (mb->name);
1181                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1182                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1183                         g_free (str);
1184                         g_free (name);
1185                         mono_raise_exception (exception);
1186                 }
1187
1188                 code_size = mono_array_length (code);
1189                 max_stack = 8; /* we probably need to run a verifier on the code... */
1190         }
1191
1192         stream_data_align (&assembly->code);
1193
1194         /* check for exceptions, maxstack, locals */
1195         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1196         if (maybe_small) {
1197                 if (code_size < 64 && !(code_size & 1)) {
1198                         flags = (code_size << 2) | 0x2;
1199                 } else if (code_size < 32 && (code_size & 1)) {
1200                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1201                 } else {
1202                         goto fat_header;
1203                 }
1204                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1205                 /* add to the fixup todo list */
1206                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1207                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1208                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1209                 return assembly->text_rva + idx;
1210         } 
1211 fat_header:
1212         if (num_locals)
1213                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1214         /* 
1215          * FIXME: need to set also the header size in fat_flags.
1216          * (and more sects and init locals flags)
1217          */
1218         fat_flags =  0x03;
1219         if (num_exception)
1220                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1221         if (mb->init_locals)
1222                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1223         fat_header [0] = fat_flags;
1224         fat_header [1] = (header_size / 4 ) << 4;
1225         short_value = GUINT16_TO_LE (max_stack);
1226         memcpy (fat_header + 2, &short_value, 2);
1227         int_value = GUINT32_TO_LE (code_size);
1228         memcpy (fat_header + 4, &int_value, 4);
1229         int_value = GUINT32_TO_LE (local_sig);
1230         memcpy (fat_header + 8, &int_value, 4);
1231         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1232         /* add to the fixup todo list */
1233         if (mb->ilgen && mb->ilgen->num_token_fixups)
1234                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1235         
1236         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1237         if (num_exception) {
1238                 unsigned char sheader [4];
1239                 MonoILExceptionInfo * ex_info;
1240                 MonoILExceptionBlock * ex_block;
1241                 int j;
1242
1243                 stream_data_align (&assembly->code);
1244                 /* always use fat format for now */
1245                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1246                 num_exception *= 6 * sizeof (guint32);
1247                 num_exception += 4; /* include the size of the header */
1248                 sheader [1] = num_exception & 0xff;
1249                 sheader [2] = (num_exception >> 8) & 0xff;
1250                 sheader [3] = (num_exception >> 16) & 0xff;
1251                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1252                 /* fat header, so we are already aligned */
1253                 /* reverse order */
1254                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1255                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1256                         if (ex_info->handlers) {
1257                                 int finally_start = ex_info->start + ex_info->len;
1258                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1259                                         guint32 val;
1260                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1261                                         /* the flags */
1262                                         val = GUINT32_TO_LE (ex_block->type);
1263                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1264                                         /* try offset */
1265                                         val = GUINT32_TO_LE (ex_info->start);
1266                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1267                                         /* need fault, too, probably */
1268                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1269                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1270                                         else
1271                                                 val = GUINT32_TO_LE (ex_info->len);
1272                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1273                                         /* handler offset */
1274                                         val = GUINT32_TO_LE (ex_block->start);
1275                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1276                                         /* handler len */
1277                                         val = GUINT32_TO_LE (ex_block->len);
1278                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1279                                         finally_start = ex_block->start + ex_block->len;
1280                                         if (ex_block->extype) {
1281                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1282                                         } else {
1283                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1284                                                         val = ex_block->filter_offset;
1285                                                 else
1286                                                         val = 0;
1287                                         }
1288                                         val = GUINT32_TO_LE (val);
1289                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1290                                         /*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", 
1291                                                         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);*/
1292                                 }
1293                         } else {
1294                                 g_error ("No clauses for ex info block %d", i);
1295                         }
1296                 }
1297         }
1298         return assembly->text_rva + idx;
1299 }
1300
1301 static guint32
1302 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1303 {
1304         MONO_REQ_GC_NEUTRAL_MODE;
1305
1306         int i;
1307         MonoDynamicTable *table;
1308         guint32 *values;
1309         
1310         table = &assembly->tables [table_idx];
1311
1312         g_assert (col < table->columns);
1313
1314         values = table->values + table->columns;
1315         for (i = 1; i <= table->rows; ++i) {
1316                 if (values [col] == token)
1317                         return i;
1318                 values += table->columns;
1319         }
1320         return 0;
1321 }
1322
1323 /*
1324  * LOCKING: Acquires the loader lock. 
1325  */
1326 static MonoCustomAttrInfo*
1327 lookup_custom_attr (MonoImage *image, gpointer member)
1328 {
1329         MONO_REQ_GC_NEUTRAL_MODE;
1330
1331         MonoCustomAttrInfo* res;
1332
1333         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1334
1335         if (!res)
1336                 return NULL;
1337
1338         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1339         res->cached = 0;
1340         return res;
1341 }
1342
1343 static gboolean
1344 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1345 {
1346         MONO_REQ_GC_UNSAFE_MODE;
1347
1348         /* FIXME: Need to do more checks */
1349         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1350                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1351
1352                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1353                         return FALSE;
1354         }
1355
1356         return TRUE;
1357 }
1358
1359 static MonoCustomAttrInfo*
1360 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1361 {
1362         MONO_REQ_GC_UNSAFE_MODE;
1363
1364         int i, index, count, not_visible;
1365         MonoCustomAttrInfo *ainfo;
1366         MonoReflectionCustomAttr *cattr;
1367
1368         if (!cattrs)
1369                 return NULL;
1370         /* FIXME: check in assembly the Run flag is set */
1371
1372         count = mono_array_length (cattrs);
1373
1374         /* Skip nonpublic attributes since MS.NET seems to do the same */
1375         /* FIXME: This needs to be done more globally */
1376         not_visible = 0;
1377         for (i = 0; i < count; ++i) {
1378                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1379                 if (!custom_attr_visible (image, cattr))
1380                         not_visible ++;
1381         }
1382         count -= not_visible;
1383
1384         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1385
1386         ainfo->image = image;
1387         ainfo->num_attrs = count;
1388         ainfo->cached = alloc_img != NULL;
1389         index = 0;
1390         for (i = 0; i < count; ++i) {
1391                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1392                 if (custom_attr_visible (image, cattr)) {
1393                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1394                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1395                         ainfo->attrs [index].ctor = cattr->ctor->method;
1396                         ainfo->attrs [index].data = saved;
1397                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1398                         index ++;
1399                 }
1400         }
1401
1402         return ainfo;
1403 }
1404
1405 #ifndef DISABLE_REFLECTION_EMIT
1406 /*
1407  * LOCKING: Acquires the loader lock. 
1408  */
1409 static void
1410 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1411 {
1412         MONO_REQ_GC_UNSAFE_MODE;
1413
1414         MonoCustomAttrInfo *ainfo, *tmp;
1415
1416         if (!cattrs || !mono_array_length (cattrs))
1417                 return;
1418
1419         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1420
1421         mono_loader_lock ();
1422         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1423         if (tmp)
1424                 mono_custom_attrs_free (tmp);
1425         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1426         mono_loader_unlock ();
1427
1428 }
1429 #endif
1430
1431 void
1432 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1433 {
1434         MONO_REQ_GC_NEUTRAL_MODE;
1435
1436         if (!ainfo->cached)
1437                 g_free (ainfo);
1438 }
1439
1440 /*
1441  * idx is the table index of the object
1442  * type is one of MONO_CUSTOM_ATTR_*
1443  */
1444 static void
1445 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1446 {
1447         MONO_REQ_GC_UNSAFE_MODE;
1448
1449         MonoDynamicTable *table;
1450         MonoReflectionCustomAttr *cattr;
1451         guint32 *values;
1452         guint32 count, i, token;
1453         char blob_size [6];
1454         char *p = blob_size;
1455         
1456         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1457         if (!cattrs)
1458                 return;
1459         count = mono_array_length (cattrs);
1460         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1461         table->rows += count;
1462         alloc_table (table, table->rows);
1463         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1464         idx <<= MONO_CUSTOM_ATTR_BITS;
1465         idx |= type;
1466         for (i = 0; i < count; ++i) {
1467                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1469                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1470                 type = mono_metadata_token_index (token);
1471                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1472                 switch (mono_metadata_token_table (token)) {
1473                 case MONO_TABLE_METHOD:
1474                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1475                         /*
1476                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1477                          * method, not the one returned by mono_image_create_token ().
1478                          */
1479                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1480                         break;
1481                 case MONO_TABLE_MEMBERREF:
1482                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1483                         break;
1484                 default:
1485                         g_warning ("got wrong token in custom attr");
1486                         continue;
1487                 }
1488                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1489                 p = blob_size;
1490                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1491                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1492                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1493                 values += MONO_CUSTOM_ATTR_SIZE;
1494                 ++table->next_idx;
1495         }
1496 }
1497
1498 static void
1499 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1500 {
1501         MONO_REQ_GC_UNSAFE_MODE;
1502
1503         MonoDynamicTable *table;
1504         guint32 *values;
1505         guint32 count, i, idx;
1506         MonoReflectionPermissionSet *perm;
1507
1508         if (!permissions)
1509                 return;
1510
1511         count = mono_array_length (permissions);
1512         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1513         table->rows += count;
1514         alloc_table (table, table->rows);
1515
1516         for (i = 0; i < mono_array_length (permissions); ++i) {
1517                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1518
1519                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1520
1521                 idx = mono_metadata_token_index (parent_token);
1522                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1523                 switch (mono_metadata_token_table (parent_token)) {
1524                 case MONO_TABLE_TYPEDEF:
1525                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1526                         break;
1527                 case MONO_TABLE_METHOD:
1528                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1529                         break;
1530                 case MONO_TABLE_ASSEMBLY:
1531                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1532                         break;
1533                 default:
1534                         g_assert_not_reached ();
1535                 }
1536
1537                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1538                 values [MONO_DECL_SECURITY_PARENT] = idx;
1539                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1540
1541                 ++table->next_idx;
1542         }
1543 }
1544
1545 /*
1546  * Fill in the MethodDef and ParamDef tables for a method.
1547  * This is used for both normal methods and constructors.
1548  */
1549 static void
1550 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1551 {
1552         MONO_REQ_GC_UNSAFE_MODE;
1553
1554         MonoDynamicTable *table;
1555         guint32 *values;
1556         guint i, count;
1557
1558         /* room in this table is already allocated */
1559         table = &assembly->tables [MONO_TABLE_METHOD];
1560         *mb->table_idx = table->next_idx ++;
1561         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1562         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1563         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1564         values [MONO_METHOD_FLAGS] = mb->attrs;
1565         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1566         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1567         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1568         
1569         table = &assembly->tables [MONO_TABLE_PARAM];
1570         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1571
1572         mono_image_add_decl_security (assembly, 
1573                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1574
1575         if (mb->pinfo) {
1576                 MonoDynamicTable *mtable;
1577                 guint32 *mvalues;
1578                 
1579                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1580                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1581                 
1582                 count = 0;
1583                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1584                         if (mono_array_get (mb->pinfo, gpointer, i))
1585                                 count++;
1586                 }
1587                 table->rows += count;
1588                 alloc_table (table, table->rows);
1589                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1590                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1591                         MonoReflectionParamBuilder *pb;
1592                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1593                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1594                                 values [MONO_PARAM_SEQUENCE] = i;
1595                                 if (pb->name != NULL) {
1596                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1597                                 } else {
1598                                         values [MONO_PARAM_NAME] = 0;
1599                                 }
1600                                 values += MONO_PARAM_SIZE;
1601                                 if (pb->marshal_info) {
1602                                         mtable->rows++;
1603                                         alloc_table (mtable, mtable->rows);
1604                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1605                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1606                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1607                                 }
1608                                 pb->table_idx = table->next_idx++;
1609                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1610                                         guint32 field_type = 0;
1611                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1612                                         mtable->rows ++;
1613                                         alloc_table (mtable, mtable->rows);
1614                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1615                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1616                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1617                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1618                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1619                                 }
1620                         }
1621                 }
1622         }
1623 }
1624
1625 #ifndef DISABLE_REFLECTION_EMIT
1626 static void
1627 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1628 {
1629         MONO_REQ_GC_UNSAFE_MODE;
1630
1631         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1632
1633         rmb->ilgen = mb->ilgen;
1634         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1635         rmb->parameters = mb->parameters;
1636         rmb->generic_params = mb->generic_params;
1637         rmb->generic_container = mb->generic_container;
1638         rmb->opt_types = NULL;
1639         rmb->pinfo = mb->pinfo;
1640         rmb->attrs = mb->attrs;
1641         rmb->iattrs = mb->iattrs;
1642         rmb->call_conv = mb->call_conv;
1643         rmb->code = mb->code;
1644         rmb->type = mb->type;
1645         rmb->name = mb->name;
1646         rmb->table_idx = &mb->table_idx;
1647         rmb->init_locals = mb->init_locals;
1648         rmb->skip_visibility = FALSE;
1649         rmb->return_modreq = mb->return_modreq;
1650         rmb->return_modopt = mb->return_modopt;
1651         rmb->param_modreq = mb->param_modreq;
1652         rmb->param_modopt = mb->param_modopt;
1653         rmb->permissions = mb->permissions;
1654         rmb->mhandle = mb->mhandle;
1655         rmb->nrefs = 0;
1656         rmb->refs = NULL;
1657
1658         if (mb->dll) {
1659                 rmb->charset = mb->charset;
1660                 rmb->extra_flags = mb->extra_flags;
1661                 rmb->native_cc = mb->native_cc;
1662                 rmb->dllentry = mb->dllentry;
1663                 rmb->dll = mb->dll;
1664         }
1665 }
1666
1667 static void
1668 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1669 {
1670         MONO_REQ_GC_UNSAFE_MODE;
1671
1672         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1673
1674         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1675
1676         rmb->ilgen = mb->ilgen;
1677         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1678         rmb->parameters = mb->parameters;
1679         rmb->generic_params = NULL;
1680         rmb->generic_container = NULL;
1681         rmb->opt_types = NULL;
1682         rmb->pinfo = mb->pinfo;
1683         rmb->attrs = mb->attrs;
1684         rmb->iattrs = mb->iattrs;
1685         rmb->call_conv = mb->call_conv;
1686         rmb->code = NULL;
1687         rmb->type = mb->type;
1688         rmb->name = mono_string_new (mono_domain_get (), name);
1689         rmb->table_idx = &mb->table_idx;
1690         rmb->init_locals = mb->init_locals;
1691         rmb->skip_visibility = FALSE;
1692         rmb->return_modreq = NULL;
1693         rmb->return_modopt = NULL;
1694         rmb->param_modreq = mb->param_modreq;
1695         rmb->param_modopt = mb->param_modopt;
1696         rmb->permissions = mb->permissions;
1697         rmb->mhandle = mb->mhandle;
1698         rmb->nrefs = 0;
1699         rmb->refs = NULL;
1700 }
1701
1702 static void
1703 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1704 {
1705         MONO_REQ_GC_UNSAFE_MODE;
1706
1707         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1708
1709         rmb->ilgen = mb->ilgen;
1710         rmb->rtype = mb->rtype;
1711         rmb->parameters = mb->parameters;
1712         rmb->generic_params = NULL;
1713         rmb->generic_container = NULL;
1714         rmb->opt_types = NULL;
1715         rmb->pinfo = NULL;
1716         rmb->attrs = mb->attrs;
1717         rmb->iattrs = 0;
1718         rmb->call_conv = mb->call_conv;
1719         rmb->code = NULL;
1720         rmb->type = (MonoObject *) mb->owner;
1721         rmb->name = mb->name;
1722         rmb->table_idx = NULL;
1723         rmb->init_locals = mb->init_locals;
1724         rmb->skip_visibility = mb->skip_visibility;
1725         rmb->return_modreq = NULL;
1726         rmb->return_modopt = NULL;
1727         rmb->param_modreq = NULL;
1728         rmb->param_modopt = NULL;
1729         rmb->permissions = NULL;
1730         rmb->mhandle = mb->mhandle;
1731         rmb->nrefs = 0;
1732         rmb->refs = NULL;
1733 }       
1734 #endif
1735
1736 static void
1737 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1738 {
1739         MONO_REQ_GC_UNSAFE_MODE;
1740
1741         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1742         MonoDynamicTable *table;
1743         guint32 *values;
1744         guint32 tok;
1745         MonoReflectionMethod *m;
1746         int i;
1747
1748         if (!mb->override_methods)
1749                 return;
1750
1751         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1752                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1753
1754                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1755                 table->rows ++;
1756                 alloc_table (table, table->rows);
1757                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1758                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1759                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1760
1761                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1762                 switch (mono_metadata_token_table (tok)) {
1763                 case MONO_TABLE_MEMBERREF:
1764                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1765                         break;
1766                 case MONO_TABLE_METHOD:
1767                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1768                         break;
1769                 default:
1770                         g_assert_not_reached ();
1771                 }
1772                 values [MONO_METHODIMPL_DECLARATION] = tok;
1773         }
1774 }
1775
1776 #ifndef DISABLE_REFLECTION_EMIT
1777 static void
1778 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1779 {
1780         MONO_REQ_GC_UNSAFE_MODE;
1781
1782         MonoDynamicTable *table;
1783         guint32 *values;
1784         ReflectionMethodBuilder rmb;
1785         int i;
1786
1787         reflection_methodbuilder_from_method_builder (&rmb, mb);
1788
1789         mono_image_basic_method (&rmb, assembly);
1790         mb->table_idx = *rmb.table_idx;
1791
1792         if (mb->dll) { /* It's a P/Invoke method */
1793                 guint32 moduleref;
1794                 /* map CharSet values to on-disk values */
1795                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1796                 int extra_flags = mb->extra_flags;
1797                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1798                 table->rows ++;
1799                 alloc_table (table, table->rows);
1800                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1801                 
1802                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1803                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1804                 if (mb->dllentry)
1805                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1806                 else
1807                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1808                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1809                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1810                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1811                         table->rows ++;
1812                         alloc_table (table, table->rows);
1813                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1814                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1815                 }
1816         }
1817
1818         if (mb->generic_params) {
1819                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1820                 table->rows += mono_array_length (mb->generic_params);
1821                 alloc_table (table, table->rows);
1822                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1823                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1824
1825                         mono_image_get_generic_param_info (
1826                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1827                 }
1828         }
1829
1830 }
1831
1832 static void
1833 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1834 {
1835         MONO_REQ_GC_UNSAFE_MODE;
1836
1837         ReflectionMethodBuilder rmb;
1838
1839         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1840
1841         mono_image_basic_method (&rmb, assembly);
1842         mb->table_idx = *rmb.table_idx;
1843 }
1844 #endif
1845
1846 static char*
1847 type_get_fully_qualified_name (MonoType *type)
1848 {
1849         MONO_REQ_GC_NEUTRAL_MODE;
1850
1851         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1852 }
1853
1854 static char*
1855 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1856 {
1857         MONO_REQ_GC_UNSAFE_MODE;
1858
1859         MonoClass *klass;
1860         MonoAssembly *ta;
1861
1862         klass = mono_class_from_mono_type (type);
1863         if (!klass) 
1864                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1865         ta = klass->image->assembly;
1866         if (assembly_is_dynamic (ta) || (ta == ass)) {
1867                 if (klass->generic_class || klass->generic_container)
1868                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1869                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1870                 else
1871                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1872         }
1873
1874         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1875 }
1876
1877 #ifndef DISABLE_REFLECTION_EMIT
1878 /*field_image is the image to which the eventual custom mods have been encoded against*/
1879 static guint32
1880 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1881 {
1882         MONO_REQ_GC_NEUTRAL_MODE;
1883
1884         SigBuffer buf;
1885         guint32 idx, i, token;
1886
1887         if (!assembly->save)
1888                 return 0;
1889
1890         sigbuffer_init (&buf, 32);
1891         
1892         sigbuffer_add_value (&buf, 0x06);
1893         /* encode custom attributes before the type */
1894         if (type->num_mods) {
1895                 for (i = 0; i < type->num_mods; ++i) {
1896                         if (field_image) {
1897                                 MonoError error;
1898                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1899                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1900
1901                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1902                         } else {
1903                                 token = type->modifiers [i].token;
1904                         }
1905
1906                         if (type->modifiers [i].required)
1907                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1908                         else
1909                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1910
1911                         sigbuffer_add_value (&buf, token);
1912                 }
1913         }
1914         encode_type (assembly, type, &buf);
1915         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1916         sigbuffer_free (&buf);
1917         return idx;
1918 }
1919 #endif
1920
1921 static guint32
1922 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1923 {
1924         MONO_REQ_GC_UNSAFE_MODE;
1925
1926         SigBuffer buf;
1927         guint32 idx;
1928         guint32 typespec = 0;
1929         MonoType *type;
1930         MonoClass *klass;
1931
1932         init_type_builder_generics (fb->type);
1933
1934         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1935         klass = mono_class_from_mono_type (type);
1936
1937         sigbuffer_init (&buf, 32);
1938         
1939         sigbuffer_add_value (&buf, 0x06);
1940         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1941         /* encode custom attributes before the type */
1942
1943         if (klass->generic_container)
1944                 typespec = create_typespec (assembly, type);
1945
1946         if (typespec) {
1947                 MonoGenericClass *gclass;
1948                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1949                 encode_generic_class (assembly, gclass, &buf);
1950         } else {
1951                 encode_type (assembly, type, &buf);
1952         }
1953         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1954         sigbuffer_free (&buf);
1955         return idx;
1956 }
1957
1958 static guint32
1959 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1960 {
1961         MONO_REQ_GC_UNSAFE_MODE;
1962
1963         char blob_size [64];
1964         char *b = blob_size;
1965         char *box_val;
1966         char* buf;
1967         guint32 idx = 0, len = 0, dummy = 0;
1968
1969         buf = (char *)g_malloc (64);
1970         if (!val) {
1971                 *ret_type = MONO_TYPE_CLASS;
1972                 len = 4;
1973                 box_val = (char*)&dummy;
1974         } else {
1975                 box_val = ((char*)val) + sizeof (MonoObject);
1976                 *ret_type = val->vtable->klass->byval_arg.type;
1977         }
1978 handle_enum:
1979         switch (*ret_type) {
1980         case MONO_TYPE_BOOLEAN:
1981         case MONO_TYPE_U1:
1982         case MONO_TYPE_I1:
1983                 len = 1;
1984                 break;
1985         case MONO_TYPE_CHAR:
1986         case MONO_TYPE_U2:
1987         case MONO_TYPE_I2:
1988                 len = 2;
1989                 break;
1990         case MONO_TYPE_U4:
1991         case MONO_TYPE_I4:
1992         case MONO_TYPE_R4:
1993                 len = 4;
1994                 break;
1995         case MONO_TYPE_U8:
1996         case MONO_TYPE_I8:
1997                 len = 8;
1998                 break;
1999         case MONO_TYPE_R8:
2000                 len = 8;
2001                 break;
2002         case MONO_TYPE_VALUETYPE: {
2003                 MonoClass *klass = val->vtable->klass;
2004                 
2005                 if (klass->enumtype) {
2006                         *ret_type = mono_class_enum_basetype (klass)->type;
2007                         goto handle_enum;
2008                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2009                         len = 8;
2010                 } else 
2011                         g_error ("we can't encode valuetypes, we should have never reached this line");
2012                 break;
2013         }
2014         case MONO_TYPE_CLASS:
2015                 break;
2016         case MONO_TYPE_STRING: {
2017                 MonoString *str = (MonoString*)val;
2018                 /* there is no signature */
2019                 len = str->length * 2;
2020                 mono_metadata_encode_value (len, b, &b);
2021 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2022                 {
2023                         char *swapped = g_malloc (2 * mono_string_length (str));
2024                         const char *p = (const char*)mono_string_chars (str);
2025
2026                         swap_with_size (swapped, p, 2, mono_string_length (str));
2027                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2028                         g_free (swapped);
2029                 }
2030 #else
2031                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2032 #endif
2033
2034                 g_free (buf);
2035                 return idx;
2036         }
2037         case MONO_TYPE_GENERICINST:
2038                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2039                 goto handle_enum;
2040         default:
2041                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2042         }
2043
2044         /* there is no signature */
2045         mono_metadata_encode_value (len, b, &b);
2046 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2047         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2048         swap_with_size (blob_size, box_val, len, 1);
2049         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2050 #else
2051         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2052 #endif
2053
2054         g_free (buf);
2055         return idx;
2056 }
2057
2058 static guint32
2059 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2060 {
2061         MONO_REQ_GC_UNSAFE_MODE;
2062
2063         char *str;
2064         SigBuffer buf;
2065         guint32 idx, len;
2066
2067         sigbuffer_init (&buf, 32);
2068
2069         sigbuffer_add_value (&buf, minfo->type);
2070
2071         switch (minfo->type) {
2072         case MONO_NATIVE_BYVALTSTR:
2073         case MONO_NATIVE_BYVALARRAY:
2074                 sigbuffer_add_value (&buf, minfo->count);
2075                 break;
2076         case MONO_NATIVE_LPARRAY:
2077                 if (minfo->eltype || minfo->has_size) {
2078                         sigbuffer_add_value (&buf, minfo->eltype);
2079                         if (minfo->has_size) {
2080                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2081                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2082
2083                                 /* LAMESPEC: ElemMult is undocumented */
2084                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2085                         }
2086                 }
2087                 break;
2088         case MONO_NATIVE_SAFEARRAY:
2089                 if (minfo->eltype)
2090                         sigbuffer_add_value (&buf, minfo->eltype);
2091                 break;
2092         case MONO_NATIVE_CUSTOM:
2093                 if (minfo->guid) {
2094                         str = mono_string_to_utf8 (minfo->guid);
2095                         len = strlen (str);
2096                         sigbuffer_add_value (&buf, len);
2097                         sigbuffer_add_mem (&buf, str, len);
2098                         g_free (str);
2099                 } else {
2100                         sigbuffer_add_value (&buf, 0);
2101                 }
2102                 /* native type name */
2103                 sigbuffer_add_value (&buf, 0);
2104                 /* custom marshaler type name */
2105                 if (minfo->marshaltype || minfo->marshaltyperef) {
2106                         if (minfo->marshaltyperef)
2107                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2108                         else
2109                                 str = mono_string_to_utf8 (minfo->marshaltype);
2110                         len = strlen (str);
2111                         sigbuffer_add_value (&buf, len);
2112                         sigbuffer_add_mem (&buf, str, len);
2113                         g_free (str);
2114                 } else {
2115                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2116                         sigbuffer_add_value (&buf, 0);
2117                 }
2118                 if (minfo->mcookie) {
2119                         str = mono_string_to_utf8 (minfo->mcookie);
2120                         len = strlen (str);
2121                         sigbuffer_add_value (&buf, len);
2122                         sigbuffer_add_mem (&buf, str, len);
2123                         g_free (str);
2124                 } else {
2125                         sigbuffer_add_value (&buf, 0);
2126                 }
2127                 break;
2128         default:
2129                 break;
2130         }
2131         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2132         sigbuffer_free (&buf);
2133         return idx;
2134 }
2135
2136 static void
2137 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2138 {
2139         MONO_REQ_GC_UNSAFE_MODE;
2140
2141         MonoDynamicTable *table;
2142         guint32 *values;
2143
2144         /* maybe this fixup should be done in the C# code */
2145         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2146                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2147         table = &assembly->tables [MONO_TABLE_FIELD];
2148         fb->table_idx = table->next_idx ++;
2149         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2150         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2151         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2152         values [MONO_FIELD_FLAGS] = fb->attrs;
2153         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2154
2155         if (fb->offset != -1) {
2156                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2157                 table->rows ++;
2158                 alloc_table (table, table->rows);
2159                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2160                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2161                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2162         }
2163         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2164                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2165                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2166                 table->rows ++;
2167                 alloc_table (table, table->rows);
2168                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2169                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2170                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2171                 values [MONO_CONSTANT_TYPE] = field_type;
2172                 values [MONO_CONSTANT_PADDING] = 0;
2173         }
2174         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2175                 guint32 rva_idx;
2176                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2177                 table->rows ++;
2178                 alloc_table (table, table->rows);
2179                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2180                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2181                 /*
2182                  * We store it in the code section because it's simpler for now.
2183                  */
2184                 if (fb->rva_data) {
2185                         if (mono_array_length (fb->rva_data) >= 10)
2186                                 stream_data_align (&assembly->code);
2187                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2188                 } else
2189                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2190                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2191         }
2192         if (fb->marshal_info) {
2193                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2194                 table->rows ++;
2195                 alloc_table (table, table->rows);
2196                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2197                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2198                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2199         }
2200 }
2201
2202 static guint32
2203 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2204 {
2205         MONO_REQ_GC_UNSAFE_MODE;
2206
2207         SigBuffer buf;
2208         guint32 nparams = 0;
2209         MonoReflectionMethodBuilder *mb = fb->get_method;
2210         MonoReflectionMethodBuilder *smb = fb->set_method;
2211         guint32 idx, i;
2212
2213         if (mb && mb->parameters)
2214                 nparams = mono_array_length (mb->parameters);
2215         if (!mb && smb && smb->parameters)
2216                 nparams = mono_array_length (smb->parameters) - 1;
2217         sigbuffer_init (&buf, 32);
2218         if (fb->call_conv & 0x20)
2219                 sigbuffer_add_byte (&buf, 0x28);
2220         else
2221                 sigbuffer_add_byte (&buf, 0x08);
2222         sigbuffer_add_value (&buf, nparams);
2223         if (mb) {
2224                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2225                 for (i = 0; i < nparams; ++i) {
2226                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2227                         encode_reflection_type (assembly, pt, &buf);
2228                 }
2229         } else if (smb && smb->parameters) {
2230                 /* the property type is the last param */
2231                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2232                 for (i = 0; i < nparams; ++i) {
2233                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2234                         encode_reflection_type (assembly, pt, &buf);
2235                 }
2236         } else {
2237                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2238         }
2239
2240         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2241         sigbuffer_free (&buf);
2242         return idx;
2243 }
2244
2245 static void
2246 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2247 {
2248         MONO_REQ_GC_UNSAFE_MODE;
2249
2250         MonoDynamicTable *table;
2251         guint32 *values;
2252         guint num_methods = 0;
2253         guint32 semaidx;
2254
2255         /* 
2256          * we need to set things in the following tables:
2257          * PROPERTYMAP (info already filled in _get_type_info ())
2258          * PROPERTY    (rows already preallocated in _get_type_info ())
2259          * METHOD      (method info already done with the generic method code)
2260          * METHODSEMANTICS
2261          * CONSTANT
2262          */
2263         table = &assembly->tables [MONO_TABLE_PROPERTY];
2264         pb->table_idx = table->next_idx ++;
2265         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2266         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2267         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2268         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2269
2270         /* FIXME: we still don't handle 'other' methods */
2271         if (pb->get_method) num_methods ++;
2272         if (pb->set_method) num_methods ++;
2273
2274         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2275         table->rows += num_methods;
2276         alloc_table (table, table->rows);
2277
2278         if (pb->get_method) {
2279                 semaidx = table->next_idx ++;
2280                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2281                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2282                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2283                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2284         }
2285         if (pb->set_method) {
2286                 semaidx = table->next_idx ++;
2287                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2288                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2289                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2290                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2291         }
2292         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2293                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2294                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2295                 table->rows ++;
2296                 alloc_table (table, table->rows);
2297                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2298                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2299                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2300                 values [MONO_CONSTANT_TYPE] = field_type;
2301                 values [MONO_CONSTANT_PADDING] = 0;
2302         }
2303 }
2304
2305 static void
2306 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2307 {
2308         MONO_REQ_GC_UNSAFE_MODE;
2309
2310         MonoDynamicTable *table;
2311         guint32 *values;
2312         guint num_methods = 0;
2313         guint32 semaidx;
2314
2315         /* 
2316          * we need to set things in the following tables:
2317          * EVENTMAP (info already filled in _get_type_info ())
2318          * EVENT    (rows already preallocated in _get_type_info ())
2319          * METHOD      (method info already done with the generic method code)
2320          * METHODSEMANTICS
2321          */
2322         table = &assembly->tables [MONO_TABLE_EVENT];
2323         eb->table_idx = table->next_idx ++;
2324         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2325         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2326         values [MONO_EVENT_FLAGS] = eb->attrs;
2327         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2328
2329         /*
2330          * FIXME: we still don't handle 'other' methods 
2331          */
2332         if (eb->add_method) num_methods ++;
2333         if (eb->remove_method) num_methods ++;
2334         if (eb->raise_method) num_methods ++;
2335
2336         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2337         table->rows += num_methods;
2338         alloc_table (table, table->rows);
2339
2340         if (eb->add_method) {
2341                 semaidx = table->next_idx ++;
2342                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2343                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2344                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2345                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2346         }
2347         if (eb->remove_method) {
2348                 semaidx = table->next_idx ++;
2349                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2350                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2351                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2352                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2353         }
2354         if (eb->raise_method) {
2355                 semaidx = table->next_idx ++;
2356                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2357                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2358                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2359                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2360         }
2361 }
2362
2363 static void
2364 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2365 {
2366         MONO_REQ_GC_UNSAFE_MODE;
2367
2368         MonoDynamicTable *table;
2369         guint32 num_constraints, i;
2370         guint32 *values;
2371         guint32 table_idx;
2372
2373         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2374         num_constraints = gparam->iface_constraints ?
2375                 mono_array_length (gparam->iface_constraints) : 0;
2376         table->rows += num_constraints;
2377         if (gparam->base_type)
2378                 table->rows++;
2379         alloc_table (table, table->rows);
2380
2381         if (gparam->base_type) {
2382                 table_idx = table->next_idx ++;
2383                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2384
2385                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2386                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2387                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2388         }
2389
2390         for (i = 0; i < num_constraints; i++) {
2391                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2392                         gparam->iface_constraints, gpointer, i);
2393
2394                 table_idx = table->next_idx ++;
2395                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2396
2397                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2398                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2399                         assembly, mono_reflection_type_get_handle (constraint));
2400         }
2401 }
2402
2403 static void
2404 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2405 {
2406         MONO_REQ_GC_UNSAFE_MODE;
2407
2408         GenericParamTableEntry *entry;
2409
2410         /*
2411          * The GenericParam table must be sorted according to the `owner' field.
2412          * We need to do this sorting prior to writing the GenericParamConstraint
2413          * table, since we have to use the final GenericParam table indices there
2414          * and they must also be sorted.
2415          */
2416
2417         entry = g_new0 (GenericParamTableEntry, 1);
2418         entry->owner = owner;
2419         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2420         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2421         entry->gparam = gparam;
2422         
2423         g_ptr_array_add (assembly->gen_params, entry);
2424 }
2425
2426 static void
2427 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2428 {
2429         MONO_REQ_GC_UNSAFE_MODE;
2430
2431         MonoDynamicTable *table;
2432         MonoGenericParam *param;
2433         guint32 *values;
2434         guint32 table_idx;
2435
2436         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2437         table_idx = table->next_idx ++;
2438         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2439
2440         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2441
2442         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2443         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2444         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2445         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2446
2447         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2448
2449         encode_constraints (entry->gparam, table_idx, assembly);
2450 }
2451
2452 static guint32
2453 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2454 {
2455         MONO_REQ_GC_UNSAFE_MODE;
2456
2457         MonoDynamicTable *table;
2458         guint32 token;
2459         guint32 *values;
2460         guint32 cols [MONO_ASSEMBLY_SIZE];
2461         const char *pubkey;
2462         guint32 publen;
2463
2464         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2465                 return token;
2466
2467         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2468                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2469                 token = table->next_idx ++;
2470                 table->rows ++;
2471                 alloc_table (table, table->rows);
2472                 values = table->values + token * MONO_MODULEREF_SIZE;
2473                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2474
2475                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2476                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2477                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2478
2479                 return token;
2480         }
2481         
2482         if (assembly_is_dynamic (image->assembly))
2483                 /* FIXME: */
2484                 memset (cols, 0, sizeof (cols));
2485         else {
2486                 /* image->assembly->image is the manifest module */
2487                 image = image->assembly->image;
2488                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2489         }
2490
2491         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2492         token = table->next_idx ++;
2493         table->rows ++;
2494         alloc_table (table, table->rows);
2495         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2496         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2497         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2498         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2499         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2500         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2501         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2502         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2503         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2504
2505         if (strcmp ("", image->assembly->aname.culture)) {
2506                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2507                                 image->assembly->aname.culture);
2508         }
2509
2510         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2511                 guchar pubtoken [9];
2512                 pubtoken [0] = 8;
2513                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2514                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2515         } else {
2516                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2517         }
2518         token <<= MONO_RESOLUTION_SCOPE_BITS;
2519         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2520         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2521         return token;
2522 }
2523
2524 static guint32
2525 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2526 {
2527         MONO_REQ_GC_NEUTRAL_MODE;
2528
2529         MonoDynamicTable *table;
2530         guint32 *values;
2531         guint32 token;
2532         SigBuffer buf;
2533
2534         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2535                 return token;
2536
2537         sigbuffer_init (&buf, 32);
2538         switch (type->type) {
2539         case MONO_TYPE_FNPTR:
2540         case MONO_TYPE_PTR:
2541         case MONO_TYPE_SZARRAY:
2542         case MONO_TYPE_ARRAY:
2543         case MONO_TYPE_VAR:
2544         case MONO_TYPE_MVAR:
2545         case MONO_TYPE_GENERICINST:
2546                 encode_type (assembly, type, &buf);
2547                 break;
2548         case MONO_TYPE_CLASS:
2549         case MONO_TYPE_VALUETYPE: {
2550                 MonoClass *k = mono_class_from_mono_type (type);
2551                 if (!k || !k->generic_container) {
2552                         sigbuffer_free (&buf);
2553                         return 0;
2554                 }
2555                 encode_type (assembly, type, &buf);
2556                 break;
2557         }
2558         default:
2559                 sigbuffer_free (&buf);
2560                 return 0;
2561         }
2562
2563         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2564         if (assembly->save) {
2565                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2566                 alloc_table (table, table->rows + 1);
2567                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2568                 values [MONO_TYPESPEC_SIGNATURE] = token;
2569         }
2570         sigbuffer_free (&buf);
2571
2572         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2573         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2574         table->next_idx ++;
2575         return token;
2576 }
2577
2578 static guint32
2579 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2580 {
2581         MONO_REQ_GC_UNSAFE_MODE;
2582
2583         MonoDynamicTable *table;
2584         guint32 *values;
2585         guint32 token, scope, enclosing;
2586         MonoClass *klass;
2587
2588         /* if the type requires a typespec, we must try that first*/
2589         if (try_typespec && (token = create_typespec (assembly, type)))
2590                 return token;
2591         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2592         if (token)
2593                 return token;
2594         klass = mono_class_from_mono_type (type);
2595         if (!klass)
2596                 klass = mono_class_from_mono_type (type);
2597
2598         /*
2599          * If it's in the same module and not a generic type parameter:
2600          */
2601         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2602                         (type->type != MONO_TYPE_MVAR)) {
2603                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2604                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2605                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2606                 return token;
2607         }
2608
2609         if (klass->nested_in) {
2610                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2611                 /* get the typeref idx of the enclosing type */
2612                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2613                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2614         } else {
2615                 scope = resolution_scope_from_image (assembly, klass->image);
2616         }
2617         table = &assembly->tables [MONO_TABLE_TYPEREF];
2618         if (assembly->save) {
2619                 alloc_table (table, table->rows + 1);
2620                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2621                 values [MONO_TYPEREF_SCOPE] = scope;
2622                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2623                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2624         }
2625         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2626         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2627         table->next_idx ++;
2628         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2629         return token;
2630 }
2631
2632 /*
2633  * Despite the name, we handle also TypeSpec (with the above helper).
2634  */
2635 static guint32
2636 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2637 {
2638         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2639 }
2640
2641 #ifndef DISABLE_REFLECTION_EMIT
2642 static guint32
2643 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2644 {
2645         MONO_REQ_GC_NEUTRAL_MODE;
2646
2647         MonoDynamicTable *table;
2648         guint32 *values;
2649         guint32 token, pclass;
2650
2651         switch (parent & MONO_TYPEDEFORREF_MASK) {
2652         case MONO_TYPEDEFORREF_TYPEREF:
2653                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2654                 break;
2655         case MONO_TYPEDEFORREF_TYPESPEC:
2656                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2657                 break;
2658         case MONO_TYPEDEFORREF_TYPEDEF:
2659                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2660                 break;
2661         default:
2662                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2663                 return 0;
2664         }
2665         /* extract the index */
2666         parent >>= MONO_TYPEDEFORREF_BITS;
2667
2668         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2669
2670         if (assembly->save) {
2671                 alloc_table (table, table->rows + 1);
2672                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2673                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2674                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2675                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2676         }
2677
2678         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2679         table->next_idx ++;
2680
2681         return token;
2682 }
2683
2684 /*
2685  * Insert a memberef row into the metadata: the token that point to the memberref
2686  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2687  * mono_image_get_fieldref_token()).
2688  * The sig param is an index to an already built signature.
2689  */
2690 static guint32
2691 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2692 {
2693         MONO_REQ_GC_NEUTRAL_MODE;
2694
2695         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2696         return mono_image_add_memberef_row (assembly, parent, name, sig);
2697 }
2698
2699
2700 static guint32
2701 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2702 {
2703         MONO_REQ_GC_NEUTRAL_MODE;
2704
2705         guint32 token;
2706         MonoMethodSignature *sig;
2707         
2708         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2709
2710         if (create_typespec) {
2711                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2712                 if (token)
2713                         return token;
2714         } 
2715
2716         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2717         if (token && !create_typespec)
2718                 return token;
2719
2720         g_assert (!method->is_inflated);
2721         if (!token) {
2722                 /*
2723                  * A methodref signature can't contain an unmanaged calling convention.
2724                  */
2725                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2726                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2727                         sig->call_convention = MONO_CALL_DEFAULT;
2728                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2729                         method->name,  method_encode_signature (assembly, sig));
2730                 g_free (sig);
2731                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2732         }
2733
2734         if (create_typespec) {
2735                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2736                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2737                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2738
2739                 if (assembly->save) {
2740                         guint32 *values;
2741
2742                         alloc_table (table, table->rows + 1);
2743                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2744                         values [MONO_METHODSPEC_METHOD] = token;
2745                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2746                 }
2747
2748                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2749                 table->next_idx ++;
2750                 /*methodspec and memberef tokens are diferent, */
2751                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2752                 return token;
2753         }
2754         return token;
2755 }
2756
2757 static guint32
2758 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2759 {
2760         guint32 token, parent, sig;
2761         ReflectionMethodBuilder rmb;
2762         char *name;
2763         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2764         
2765         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2766         if (token)
2767                 return token;
2768
2769         name = mono_string_to_utf8 (method->name);
2770         reflection_methodbuilder_from_method_builder (&rmb, method);
2771
2772         /*
2773          * A methodref signature can't contain an unmanaged calling convention.
2774          * Since some flags are encoded as part of call_conv, we need to check against it.
2775         */
2776         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2777                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2778
2779         sig = method_builder_encode_signature (assembly, &rmb);
2780
2781         if (tb->generic_params)
2782                 parent = create_generic_typespec (assembly, tb);
2783         else
2784                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2785
2786         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2787
2788         g_free (name);
2789         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2790         return token;
2791 }
2792
2793 static guint32
2794 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2795                                      const gchar *name, guint32 sig)
2796 {
2797         MonoDynamicTable *table;
2798         guint32 token;
2799         guint32 *values;
2800         
2801         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2802
2803         if (assembly->save) {
2804                 alloc_table (table, table->rows + 1);
2805                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2806                 values [MONO_MEMBERREF_CLASS] = original;
2807                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2808                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2809         }
2810
2811         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2812         table->next_idx ++;
2813
2814         return token;
2815 }
2816
2817 static guint32
2818 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2819 {
2820         SigBuffer buf;
2821         int i;
2822         guint32 nparams = mono_array_length (mb->generic_params);
2823         guint32 idx;
2824
2825         if (!assembly->save)
2826                 return 0;
2827
2828         sigbuffer_init (&buf, 32);
2829
2830         sigbuffer_add_value (&buf, 0xa);
2831         sigbuffer_add_value (&buf, nparams);
2832
2833         for (i = 0; i < nparams; i++) {
2834                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2835                 sigbuffer_add_value (&buf, i);
2836         }
2837
2838         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2839         sigbuffer_free (&buf);
2840         return idx;
2841 }
2842
2843 static guint32
2844 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2845 {
2846         MonoDynamicTable *table;
2847         guint32 *values;
2848         guint32 token, mtoken = 0;
2849
2850         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2851         if (token)
2852                 return token;
2853
2854         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2855
2856         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2857         switch (mono_metadata_token_table (mtoken)) {
2858         case MONO_TABLE_MEMBERREF:
2859                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2860                 break;
2861         case MONO_TABLE_METHOD:
2862                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2863                 break;
2864         default:
2865                 g_assert_not_reached ();
2866         }
2867
2868         if (assembly->save) {
2869                 alloc_table (table, table->rows + 1);
2870                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2871                 values [MONO_METHODSPEC_METHOD] = mtoken;
2872                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2873         }
2874
2875         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2876         table->next_idx ++;
2877
2878         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2879         return token;
2880 }
2881
2882 static guint32
2883 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2884 {
2885         guint32 token;
2886
2887         if (mb->generic_params && create_methodspec) 
2888                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2889
2890         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2891         if (token)
2892                 return token;
2893
2894         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2895         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2896         return token;
2897 }
2898
2899 static guint32
2900 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2901 {
2902         guint32 token, parent, sig;
2903         ReflectionMethodBuilder rmb;
2904         char *name;
2905         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2906         
2907         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2908         if (token)
2909                 return token;
2910
2911         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2912
2913         if (tb->generic_params)
2914                 parent = create_generic_typespec (assembly, tb);
2915         else
2916                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2917         
2918         name = mono_string_to_utf8 (rmb.name);
2919         sig = method_builder_encode_signature (assembly, &rmb);
2920
2921         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2922
2923         g_free (name);
2924         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2925         return token;
2926 }
2927 #endif
2928
2929 static gboolean
2930 is_field_on_inst (MonoClassField *field)
2931 {
2932         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2933 }
2934
2935 /*
2936  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2937  */
2938 static MonoType*
2939 get_field_on_inst_generic_type (MonoClassField *field)
2940 {
2941         MonoClass *klass, *gtd;
2942         MonoDynamicGenericClass *dgclass;
2943         int field_index;
2944
2945         g_assert (is_field_on_inst (field));
2946
2947         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2948
2949         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2950                 field_index = field - dgclass->fields;
2951                 return dgclass->field_generic_types [field_index];              
2952         }
2953
2954         klass = field->parent;
2955         gtd = klass->generic_class->container_class;
2956
2957         if (field >= klass->fields && field - klass->fields < klass->field.count) {
2958                 field_index = field - klass->fields;
2959                 return gtd->fields [field_index].type;
2960         }
2961
2962         g_assert_not_reached ();
2963         return 0;
2964 }
2965
2966 #ifndef DISABLE_REFLECTION_EMIT
2967 static guint32
2968 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2969 {
2970         MonoType *type;
2971         guint32 token;
2972
2973         g_assert (field);
2974         g_assert (field->parent);
2975
2976         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2977         if (token)
2978                 return token;
2979
2980         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2981                 int index = field - field->parent->fields;
2982                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2983         } else {
2984                 if (is_field_on_inst (field))
2985                         type = get_field_on_inst_generic_type (field);
2986                 else
2987                         type = mono_field_get_type (field);
2988         }
2989         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2990                                                                                         mono_field_get_name (field),
2991                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2992         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2993         return token;
2994 }
2995
2996 static guint32
2997 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2998 {
2999         guint32 token;
3000         MonoClass *klass;
3001         MonoGenericClass *gclass;
3002         MonoType *type;
3003         char *name;
3004
3005         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3006         if (token)
3007                 return token;
3008         if (is_sre_field_builder (mono_object_class (f->fb))) {
3009                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3010                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3011                 klass = mono_class_from_mono_type (type);
3012                 gclass = type->data.generic_class;
3013                 g_assert (gclass->is_dynamic);
3014
3015                 name = mono_string_to_utf8 (fb->name);
3016                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3017                                                                                                 field_encode_signature (assembly, fb));
3018                 g_free (name);          
3019         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3020                 guint32 sig;
3021                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3022
3023                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3024                 klass = mono_class_from_mono_type (type);
3025
3026                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3027                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3028         } else {
3029                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3030                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3031         }
3032
3033         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3034         return token;
3035 }
3036
3037 static guint32
3038 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
3039 {
3040         guint32 sig, token;
3041         MonoClass *klass;
3042         MonoGenericClass *gclass;
3043         MonoType *type;
3044
3045         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3046
3047         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3048         if (token)
3049                 return token;
3050
3051         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3052                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3053                 ReflectionMethodBuilder rmb;
3054                 char *name;
3055
3056                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3057                 klass = mono_class_from_mono_type (type);
3058
3059                 gclass = type->data.generic_class;
3060                 g_assert (gclass->is_dynamic);
3061
3062                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3063
3064                 name = mono_string_to_utf8 (rmb.name);
3065
3066                 sig = method_builder_encode_signature (assembly, &rmb);
3067
3068                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3069                 g_free (name);
3070         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3071                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3072
3073                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3074                 klass = mono_class_from_mono_type (type);
3075
3076                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3077                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3078         } else {
3079                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3080                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3081         }
3082
3083
3084         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3085         return token;
3086 }
3087
3088 static MonoMethod*
3089 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3090 {
3091         MonoError error;
3092         MonoClass *klass;
3093         MonoGenericContext tmp_context;
3094         MonoType **type_argv;
3095         MonoGenericInst *ginst;
3096         MonoMethod *method, *inflated;
3097         int count, i;
3098
3099         init_type_builder_generics ((MonoObject*)m->inst);
3100
3101         method = inflate_method (m->inst, (MonoObject*)m->mb);
3102
3103         klass = method->klass;
3104
3105         if (m->method_args == NULL)
3106                 return method;
3107
3108         if (method->is_inflated)
3109                 method = ((MonoMethodInflated *) method)->declaring;
3110
3111         count = mono_array_length (m->method_args);
3112
3113         type_argv = g_new0 (MonoType *, count);
3114         for (i = 0; i < count; i++) {
3115                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3116                 type_argv [i] = mono_reflection_type_get_handle (garg);
3117         }
3118         ginst = mono_metadata_get_generic_inst (count, type_argv);
3119         g_free (type_argv);
3120
3121         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3122         tmp_context.method_inst = ginst;
3123
3124         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3125         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3126         return inflated;
3127 }
3128
3129 static guint32
3130 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3131 {
3132         guint32 sig, token = 0;
3133         MonoType *type;
3134         MonoClass *klass;
3135
3136         if (m->method_args) {
3137                 MonoMethod *inflated;
3138
3139                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3140                 if (create_methodspec)
3141                         token = mono_image_get_methodspec_token (assembly, inflated);
3142                 else
3143                         token = mono_image_get_inflated_method_token (assembly, inflated);
3144                 return token;
3145         }
3146
3147         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3148         if (token)
3149                 return token;
3150
3151         if (is_sre_method_builder (mono_object_class (m->mb))) {
3152                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3153                 MonoGenericClass *gclass;
3154                 ReflectionMethodBuilder rmb;
3155                 char *name;
3156
3157                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3158                 klass = mono_class_from_mono_type (type);
3159                 gclass = type->data.generic_class;
3160                 g_assert (gclass->is_dynamic);
3161
3162                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3163
3164                 name = mono_string_to_utf8 (rmb.name);
3165
3166                 sig = method_builder_encode_signature (assembly, &rmb);
3167
3168                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3169                 g_free (name);          
3170         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3171                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3172
3173                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3174                 klass = mono_class_from_mono_type (type);
3175
3176                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3177                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3178         } else {
3179                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3180                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3181         }
3182
3183         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3184         return token;
3185 }
3186
3187 static guint32
3188 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3189 {
3190         SigBuffer buf;
3191         int i;
3192         guint32 nparams = context->method_inst->type_argc;
3193         guint32 idx;
3194
3195         if (!assembly->save)
3196                 return 0;
3197
3198         sigbuffer_init (&buf, 32);
3199         /*
3200          * FIXME: vararg, explicit_this, differenc call_conv values...
3201          */
3202         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3203         sigbuffer_add_value (&buf, nparams);
3204
3205         for (i = 0; i < nparams; i++)
3206                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3207
3208         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3209         sigbuffer_free (&buf);
3210         return idx;
3211 }
3212
3213 static guint32
3214 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3215 {
3216         MonoDynamicTable *table;
3217         guint32 *values;
3218         guint32 token, mtoken = 0, sig;
3219         MonoMethodInflated *imethod;
3220         MonoMethod *declaring;
3221
3222         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3223
3224         g_assert (method->is_inflated);
3225         imethod = (MonoMethodInflated *) method;
3226         declaring = imethod->declaring;
3227
3228         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3229         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3230
3231         if (!mono_method_signature (declaring)->generic_param_count)
3232                 return mtoken;
3233
3234         switch (mono_metadata_token_table (mtoken)) {
3235         case MONO_TABLE_MEMBERREF:
3236                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3237                 break;
3238         case MONO_TABLE_METHOD:
3239                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3240                 break;
3241         default:
3242                 g_assert_not_reached ();
3243         }
3244
3245         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3246
3247         if (assembly->save) {
3248                 alloc_table (table, table->rows + 1);
3249                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3250                 values [MONO_METHODSPEC_METHOD] = mtoken;
3251                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3252         }
3253
3254         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3255         table->next_idx ++;
3256
3257         return token;
3258 }
3259
3260 static guint32
3261 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3262 {
3263         MonoMethodInflated *imethod;
3264         guint32 token;
3265         
3266         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3267         if (token)
3268                 return token;
3269
3270         g_assert (method->is_inflated);
3271         imethod = (MonoMethodInflated *) method;
3272
3273         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3274                 token = method_encode_methodspec (assembly, method);
3275         } else {
3276                 guint32 sig = method_encode_signature (
3277                         assembly, mono_method_signature (imethod->declaring));
3278                 token = mono_image_get_memberref_token (
3279                         assembly, &method->klass->byval_arg, method->name, sig);
3280         }
3281
3282         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3283         return token;
3284 }
3285
3286 static guint32
3287 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3288 {
3289         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3290         guint32 sig, token;
3291
3292         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3293         token = mono_image_get_memberref_token (
3294                 assembly, &m->klass->byval_arg, m->name, sig);
3295
3296         return token;
3297 }
3298
3299 static guint32
3300 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3301 {
3302         MonoDynamicTable *table;
3303         MonoClass *klass;
3304         MonoType *type;
3305         guint32 *values;
3306         guint32 token;
3307         SigBuffer buf;
3308         int count, i;
3309
3310         /*
3311          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3312          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3313          * Because of this, we must not insert it into the `typeref' hash table.
3314          */
3315         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3316         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3317         if (token)
3318                 return token;
3319
3320         sigbuffer_init (&buf, 32);
3321
3322         g_assert (tb->generic_params);
3323         klass = mono_class_from_mono_type (type);
3324
3325         if (tb->generic_container)
3326                 mono_reflection_create_generic_class (tb);
3327
3328         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3329         g_assert (klass->generic_container);
3330         sigbuffer_add_value (&buf, klass->byval_arg.type);
3331         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3332
3333         count = mono_array_length (tb->generic_params);
3334         sigbuffer_add_value (&buf, count);
3335         for (i = 0; i < count; i++) {
3336                 MonoReflectionGenericParam *gparam;
3337
3338                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3339
3340                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3341         }
3342
3343         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3344
3345         if (assembly->save) {
3346                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3347                 alloc_table (table, table->rows + 1);
3348                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3349                 values [MONO_TYPESPEC_SIGNATURE] = token;
3350         }
3351         sigbuffer_free (&buf);
3352
3353         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3354         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3355         table->next_idx ++;
3356         return token;
3357 }
3358
3359 /*
3360  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3361  */
3362 static MonoType*
3363 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3364 {
3365         int i, count, len, pos;
3366         MonoType *t;
3367
3368         count = 0;
3369         if (modreq)
3370                 count += mono_array_length (modreq);
3371         if (modopt)
3372                 count += mono_array_length (modopt);
3373
3374         if (count == 0)
3375                 return mono_metadata_type_dup (NULL, type);
3376
3377         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3378         t = (MonoType *)g_malloc (len);
3379         memcpy (t, type, MONO_SIZEOF_TYPE);
3380
3381         t->num_mods = count;
3382         pos = 0;
3383         if (modreq) {
3384                 for (i = 0; i < mono_array_length (modreq); ++i) {
3385                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3386                         t->modifiers [pos].required = 1;
3387                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3388                         pos ++;
3389                 }
3390         }
3391         if (modopt) {
3392                 for (i = 0; i < mono_array_length (modopt); ++i) {
3393                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3394                         t->modifiers [pos].required = 0;
3395                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3396                         pos ++;
3397                 }
3398         }
3399
3400         return t;
3401 }
3402
3403 static void
3404 init_type_builder_generics (MonoObject *type)
3405 {
3406         MonoReflectionTypeBuilder *tb;
3407
3408         if (!is_sre_type_builder(mono_object_class (type)))
3409                 return;
3410         tb = (MonoReflectionTypeBuilder *)type;
3411
3412         if (tb && tb->generic_container)
3413                 mono_reflection_create_generic_class (tb);
3414 }
3415
3416 static guint32
3417 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3418 {
3419         MonoDynamicTable *table;
3420         MonoType *custom = NULL, *type;
3421         guint32 *values;
3422         guint32 token, pclass, parent, sig;
3423         gchar *name;
3424
3425         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3426         if (token)
3427                 return token;
3428
3429         /* FIXME: is this call necessary? */
3430         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3431         name = mono_string_to_utf8 (fb->name);
3432
3433         /*FIXME this is one more layer of ugliness due how types are created.*/
3434         init_type_builder_generics (fb->type);
3435
3436         /* fb->type does not include the custom modifiers */
3437         /* FIXME: We should do this in one place when a fieldbuilder is created */
3438         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3439         if (fb->modreq || fb->modopt)
3440                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3441
3442         sig = fieldref_encode_signature (assembly, NULL, type);
3443         g_free (custom);
3444
3445         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3446         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3447         
3448         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3449         parent >>= MONO_TYPEDEFORREF_BITS;
3450
3451         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3452
3453         if (assembly->save) {
3454                 alloc_table (table, table->rows + 1);
3455                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3456                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3457                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3458                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3459         }
3460
3461         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3462         table->next_idx ++;
3463         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3464         g_free (name);
3465         return token;
3466 }
3467
3468 static guint32
3469 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3470 {
3471         SigBuffer buf;
3472         guint32 nargs;
3473         guint32 i, idx;
3474
3475         if (!assembly->save)
3476                 return 0;
3477
3478         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3479         g_assert (helper->type == 2);
3480
3481         if (helper->arguments)
3482                 nargs = mono_array_length (helper->arguments);
3483         else
3484                 nargs = 0;
3485
3486         sigbuffer_init (&buf, 32);
3487
3488         /* Encode calling convention */
3489         /* Change Any to Standard */
3490         if ((helper->call_conv & 0x03) == 0x03)
3491                 helper->call_conv = 0x01;
3492         /* explicit_this implies has_this */
3493         if (helper->call_conv & 0x40)
3494                 helper->call_conv &= 0x20;
3495
3496         if (helper->call_conv == 0) { /* Unmanaged */
3497                 idx = helper->unmanaged_call_conv - 1;
3498         } else {
3499                 /* Managed */
3500                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3501                 if (helper->call_conv & 0x02) /* varargs */
3502                         idx += 0x05;
3503         }
3504
3505         sigbuffer_add_byte (&buf, idx);
3506         sigbuffer_add_value (&buf, nargs);
3507         encode_reflection_type (assembly, helper->return_type, &buf);
3508         for (i = 0; i < nargs; ++i) {
3509                 MonoArray *modreqs = NULL;
3510                 MonoArray *modopts = NULL;
3511                 MonoReflectionType *pt;
3512
3513                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3514                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3515                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3516                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3517
3518                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3519                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3520                 encode_reflection_type (assembly, pt, &buf);
3521         }
3522         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3523         sigbuffer_free (&buf);
3524
3525         return idx;
3526 }
3527
3528 static guint32 
3529 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3530 {
3531         guint32 idx;
3532         MonoDynamicTable *table;
3533         guint32 *values;
3534
3535         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3536         idx = table->next_idx ++;
3537         table->rows ++;
3538         alloc_table (table, table->rows);
3539         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3540
3541         values [MONO_STAND_ALONE_SIGNATURE] =
3542                 mono_reflection_encode_sighelper (assembly, helper);
3543
3544         return idx;
3545 }
3546
3547 static int
3548 reflection_cc_to_file (int call_conv) {
3549         switch (call_conv & 0x3) {
3550         case 0:
3551         case 1: return MONO_CALL_DEFAULT;
3552         case 2: return MONO_CALL_VARARG;
3553         default:
3554                 g_assert_not_reached ();
3555         }
3556         return 0;
3557 }
3558 #endif /* !DISABLE_REFLECTION_EMIT */
3559
3560 typedef struct {
3561         MonoType *parent;
3562         MonoMethodSignature *sig;
3563         char *name;
3564         guint32 token;
3565 } ArrayMethod;
3566
3567 #ifndef DISABLE_REFLECTION_EMIT
3568 static guint32
3569 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3570 {
3571         guint32 nparams, i;
3572         GList *tmp;
3573         char *name;
3574         MonoMethodSignature *sig;
3575         ArrayMethod *am;
3576         MonoType *mtype;
3577
3578         name = mono_string_to_utf8 (m->name);
3579         nparams = mono_array_length (m->parameters);
3580         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3581         sig->hasthis = 1;
3582         sig->sentinelpos = -1;
3583         sig->call_convention = reflection_cc_to_file (m->call_conv);
3584         sig->param_count = nparams;
3585         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3586         mtype = mono_reflection_type_get_handle (m->parent);
3587         for (i = 0; i < nparams; ++i)
3588                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3589
3590         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3591                 am = (ArrayMethod *)tmp->data;
3592                 if (strcmp (name, am->name) == 0 && 
3593                                 mono_metadata_type_equal (am->parent, mtype) &&
3594                                 mono_metadata_signature_equal (am->sig, sig)) {
3595                         g_free (name);
3596                         g_free (sig);
3597                         m->table_idx = am->token & 0xffffff;
3598                         return am->token;
3599                 }
3600         }
3601         am = g_new0 (ArrayMethod, 1);
3602         am->name = name;
3603         am->sig = sig;
3604         am->parent = mtype;
3605         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3606                 method_encode_signature (assembly, sig));
3607         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3608         m->table_idx = am->token & 0xffffff;
3609         return am->token;
3610 }
3611
3612 /*
3613  * Insert into the metadata tables all the info about the TypeBuilder tb.
3614  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3615  */
3616 static void
3617 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3618 {
3619         MonoDynamicTable *table;
3620         guint *values;
3621         int i, is_object = 0, is_system = 0;
3622         char *n;
3623
3624         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3625         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3626         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3627         n = mono_string_to_utf8 (tb->name);
3628         if (strcmp (n, "Object") == 0)
3629                 is_object++;
3630         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3631         g_free (n);
3632         n = mono_string_to_utf8 (tb->nspace);
3633         if (strcmp (n, "System") == 0)
3634                 is_system++;
3635         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3636         g_free (n);
3637         if (tb->parent && !(is_system && is_object) && 
3638                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3639                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3640         } else {
3641                 values [MONO_TYPEDEF_EXTENDS] = 0;
3642         }
3643         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3644         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3645
3646         /*
3647          * if we have explicitlayout or sequentiallayouts, output data in the
3648          * ClassLayout table.
3649          */
3650         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3651                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3652                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3653                 table->rows++;
3654                 alloc_table (table, table->rows);
3655                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3656                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3657                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3658                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3659         }
3660
3661         /* handle interfaces */
3662         if (tb->interfaces) {
3663                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3664                 i = table->rows;
3665                 table->rows += mono_array_length (tb->interfaces);
3666                 alloc_table (table, table->rows);
3667                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3668                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3669                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3670                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3671                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3672                         values += MONO_INTERFACEIMPL_SIZE;
3673                 }
3674         }
3675
3676         /* handle fields */
3677         if (tb->fields) {
3678                 table = &assembly->tables [MONO_TABLE_FIELD];
3679                 table->rows += tb->num_fields;
3680                 alloc_table (table, table->rows);
3681                 for (i = 0; i < tb->num_fields; ++i)
3682                         mono_image_get_field_info (
3683                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3684         }
3685
3686         /* handle constructors */
3687         if (tb->ctors) {
3688                 table = &assembly->tables [MONO_TABLE_METHOD];
3689                 table->rows += mono_array_length (tb->ctors);
3690                 alloc_table (table, table->rows);
3691                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3692                         mono_image_get_ctor_info (domain,
3693                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3694         }
3695
3696         /* handle methods */
3697         if (tb->methods) {
3698                 table = &assembly->tables [MONO_TABLE_METHOD];
3699                 table->rows += tb->num_methods;
3700                 alloc_table (table, table->rows);
3701                 for (i = 0; i < tb->num_methods; ++i)
3702                         mono_image_get_method_info (
3703                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3704         }
3705
3706         /* Do the same with properties etc.. */
3707         if (tb->events && mono_array_length (tb->events)) {
3708                 table = &assembly->tables [MONO_TABLE_EVENT];
3709                 table->rows += mono_array_length (tb->events);
3710                 alloc_table (table, table->rows);
3711                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3712                 table->rows ++;
3713                 alloc_table (table, table->rows);
3714                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3715                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3716                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3717                 for (i = 0; i < mono_array_length (tb->events); ++i)
3718                         mono_image_get_event_info (
3719                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3720         }
3721         if (tb->properties && mono_array_length (tb->properties)) {
3722                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3723                 table->rows += mono_array_length (tb->properties);
3724                 alloc_table (table, table->rows);
3725                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3726                 table->rows ++;
3727                 alloc_table (table, table->rows);
3728                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3729                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3730                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3731                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3732                         mono_image_get_property_info (
3733                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3734         }
3735
3736         /* handle generic parameters */
3737         if (tb->generic_params) {
3738                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3739                 table->rows += mono_array_length (tb->generic_params);
3740                 alloc_table (table, table->rows);
3741                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3742                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3743
3744                         mono_image_get_generic_param_info (
3745                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3746                 }
3747         }
3748
3749         mono_image_add_decl_security (assembly, 
3750                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3751
3752         if (tb->subtypes) {
3753                 MonoDynamicTable *ntable;
3754                 
3755                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3756                 ntable->rows += mono_array_length (tb->subtypes);
3757                 alloc_table (ntable, ntable->rows);
3758                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3759
3760                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3761                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3762
3763                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3764                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3765                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3766                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3767                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3768                                 ntable->next_idx, ntable->rows);*/
3769                         values += MONO_NESTED_CLASS_SIZE;
3770                         ntable->next_idx++;
3771                 }
3772         }
3773 }
3774 #endif
3775
3776 static void
3777 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3778 {
3779         int i;
3780
3781         mono_ptr_array_append (*types, type);
3782
3783         if (!type->subtypes)
3784                 return;
3785
3786         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3787                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3788                 collect_types (types, subtype);
3789         }
3790 }
3791
3792 static gint
3793 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3794 {
3795         if ((*type1)->table_idx < (*type2)->table_idx)
3796                 return -1;
3797         else
3798                 if ((*type1)->table_idx > (*type2)->table_idx)
3799                         return 1;
3800         else
3801                 return 0;
3802 }
3803
3804 static void
3805 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3806         int i;
3807
3808         if (!pinfo)
3809                 return;
3810         for (i = 0; i < mono_array_length (pinfo); ++i) {
3811                 MonoReflectionParamBuilder *pb;
3812                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3813                 if (!pb)
3814                         continue;
3815                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3816         }
3817 }
3818
3819 static void
3820 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3821         int i;
3822         
3823         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3824         if (tb->fields) {
3825                 for (i = 0; i < tb->num_fields; ++i) {
3826                         MonoReflectionFieldBuilder* fb;
3827                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3828                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3829                 }
3830         }
3831         if (tb->events) {
3832                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3833                         MonoReflectionEventBuilder* eb;
3834                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3835                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3836                 }
3837         }
3838         if (tb->properties) {
3839                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3840                         MonoReflectionPropertyBuilder* pb;
3841                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3842                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3843                 }
3844         }
3845         if (tb->ctors) {
3846                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3847                         MonoReflectionCtorBuilder* cb;
3848                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3849                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3850                         params_add_cattrs (assembly, cb->pinfo);
3851                 }
3852         }
3853
3854         if (tb->methods) {
3855                 for (i = 0; i < tb->num_methods; ++i) {
3856                         MonoReflectionMethodBuilder* mb;
3857                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3858                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3859                         params_add_cattrs (assembly, mb->pinfo);
3860                 }
3861         }
3862
3863         if (tb->subtypes) {
3864                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3865                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3866         }
3867 }
3868
3869 static void
3870 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3871 {
3872         int i;
3873         
3874         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3875
3876         if (moduleb->global_methods) {
3877                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3878                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3879                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3880                         params_add_cattrs (assembly, mb->pinfo);
3881                 }
3882         }
3883
3884         if (moduleb->global_fields) {
3885                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3886                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3887                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3888                 }
3889         }
3890         
3891         if (moduleb->types) {
3892                 for (i = 0; i < moduleb->num_types; ++i)
3893                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3894         }
3895 }
3896
3897 static void
3898 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3899 {
3900         MonoDynamicTable *table;
3901         guint32 *values;
3902         char blob_size [6];
3903         guchar hash [20];
3904         char *b = blob_size;
3905         char *dir, *path;
3906
3907         table = &assembly->tables [MONO_TABLE_FILE];
3908         table->rows++;
3909         alloc_table (table, table->rows);
3910         values = table->values + table->next_idx * MONO_FILE_SIZE;
3911         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3912         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3913         if (image_is_dynamic (module->image)) {
3914                 /* This depends on the fact that the main module is emitted last */
3915                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3916                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3917         } else {
3918                 dir = NULL;
3919                 path = g_strdup (module->image->name);
3920         }
3921         mono_sha1_get_digest_from_file (path, hash);
3922         g_free (dir);
3923         g_free (path);
3924         mono_metadata_encode_value (20, b, &b);
3925         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3926         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3927         table->next_idx ++;
3928 }
3929
3930 static void
3931 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3932 {
3933         MonoDynamicTable *table;
3934         int i;
3935
3936         table = &assembly->tables [MONO_TABLE_MODULE];
3937         mb->table_idx = table->next_idx ++;
3938         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3939         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3940         i /= 16;
3941         ++i;
3942         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3943         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3944         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3945         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3946 }
3947
3948 static guint32
3949 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3950         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3951 {
3952         MonoDynamicTable *table;
3953         guint32 *values;
3954         guint32 visib, res;
3955
3956         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3957         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3958                 return 0;
3959
3960         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3961         table->rows++;
3962         alloc_table (table, table->rows);
3963         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3964
3965         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3966         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3967         if (klass->nested_in)
3968                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3969         else
3970                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3971         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3972         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3973
3974         res = table->next_idx;
3975
3976         table->next_idx ++;
3977
3978         /* Emit nested types */
3979         if (klass->ext && klass->ext->nested_classes) {
3980                 GList *tmp;
3981
3982                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3983                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3984         }
3985
3986         return res;
3987 }
3988
3989 static void
3990 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3991         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3992 {
3993         MonoClass *klass;
3994         guint32 idx, i;
3995
3996         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3997
3998         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3999
4000         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4001                                                                                                    parent_index, assembly);
4002
4003         /* 
4004          * Emit nested types
4005          * We need to do this ourselves since klass->nested_classes is not set up.
4006          */
4007         if (tb->subtypes) {
4008                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4009                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4010         }
4011 }
4012
4013 static void
4014 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4015         guint32 module_index, MonoDynamicImage *assembly)
4016 {
4017         MonoImage *image = module->image;
4018         MonoTableInfo  *t;
4019         guint32 i;
4020
4021         t = &image->tables [MONO_TABLE_TYPEDEF];
4022
4023         for (i = 0; i < t->rows; ++i) {
4024                 MonoError error;
4025                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4026                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4027
4028                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4029                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4030         }
4031 }
4032
4033 static void
4034 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4035 {
4036         MonoDynamicTable *table;
4037         guint32 *values;
4038         guint32 scope, scope_idx, impl, current_idx;
4039         gboolean forwarder = TRUE;
4040         gpointer iter = NULL;
4041         MonoClass *nested;
4042
4043         if (klass->nested_in) {
4044                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4045                 forwarder = FALSE;
4046         } else {
4047                 scope = resolution_scope_from_image (assembly, klass->image);
4048                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4049                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4050                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4051         }
4052
4053         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4054
4055         table->rows++;
4056         alloc_table (table, table->rows);
4057         current_idx = table->next_idx;
4058         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4059
4060         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4061         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4062         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4063         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4064         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4065
4066         table->next_idx++;
4067
4068         while ((nested = mono_class_get_nested_types (klass, &iter)))
4069                 add_exported_type (assemblyb, assembly, nested, current_idx);
4070 }
4071
4072 static void
4073 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4074 {
4075         MonoClass *klass;
4076         int i;
4077
4078         if (!assemblyb->type_forwarders)
4079                 return;
4080
4081         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4082                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4083                 MonoType *type;
4084                 if (!t)
4085                         continue;
4086
4087                 type = mono_reflection_type_get_handle (t);
4088                 g_assert (type);
4089
4090                 klass = mono_class_from_mono_type (type);
4091
4092                 add_exported_type (assemblyb, assembly, klass, 0);
4093         }
4094 }
4095
4096 #define align_pointer(base,p)\
4097         do {\
4098                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4099                 if (__diff & 3)\
4100                         (p) += 4 - (__diff & 3);\
4101         } while (0)
4102
4103 static int
4104 compare_constants (const void *a, const void *b)
4105 {
4106         const guint32 *a_values = (const guint32 *)a;
4107         const guint32 *b_values = (const guint32 *)b;
4108         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4109 }
4110
4111 static int
4112 compare_semantics (const void *a, const void *b)
4113 {
4114         const guint32 *a_values = (const guint32 *)a;
4115         const guint32 *b_values = (const guint32 *)b;
4116         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4117         if (assoc)
4118                 return assoc;
4119         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4120 }
4121
4122 static int
4123 compare_custom_attrs (const void *a, const void *b)
4124 {
4125         const guint32 *a_values = (const guint32 *)a;
4126         const guint32 *b_values = (const guint32 *)b;
4127
4128         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4129 }
4130
4131 static int
4132 compare_field_marshal (const void *a, const void *b)
4133 {
4134         const guint32 *a_values = (const guint32 *)a;
4135         const guint32 *b_values = (const guint32 *)b;
4136
4137         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4138 }
4139
4140 static int
4141 compare_nested (const void *a, const void *b)
4142 {
4143         const guint32 *a_values = (const guint32 *)a;
4144         const guint32 *b_values = (const guint32 *)b;
4145
4146         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4147 }
4148
4149 static int
4150 compare_genericparam (const void *a, const void *b)
4151 {
4152         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4153         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4154
4155         if ((*b_entry)->owner == (*a_entry)->owner)
4156                 return 
4157                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4158                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4159         else
4160                 return (*a_entry)->owner - (*b_entry)->owner;
4161 }
4162
4163 static int
4164 compare_declsecurity_attrs (const void *a, const void *b)
4165 {
4166         const guint32 *a_values = (const guint32 *)a;
4167         const guint32 *b_values = (const guint32 *)b;
4168
4169         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4170 }
4171
4172 static int
4173 compare_interface_impl (const void *a, const void *b)
4174 {
4175         const guint32 *a_values = (const guint32 *)a;
4176         const guint32 *b_values = (const guint32 *)b;
4177
4178         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4179         if (klass)
4180                 return klass;
4181
4182         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4183 }
4184
4185 static void
4186 pad_heap (MonoDynamicStream *sh)
4187 {
4188         if (sh->index & 3) {
4189                 int sz = 4 - (sh->index & 3);
4190                 memset (sh->data + sh->index, 0, sz);
4191                 sh->index += sz;
4192         }
4193 }
4194
4195 struct StreamDesc {
4196         const char *name;
4197         MonoDynamicStream *stream;
4198 };
4199
4200 /*
4201  * build_compressed_metadata() fills in the blob of data that represents the 
4202  * raw metadata as it will be saved in the PE file. The five streams are output 
4203  * and the metadata tables are comnpressed from the guint32 array representation, 
4204  * to the compressed on-disk format.
4205  */
4206 static void
4207 build_compressed_metadata (MonoDynamicImage *assembly)
4208 {
4209         MonoDynamicTable *table;
4210         int i;
4211         guint64 valid_mask = 0;
4212         guint64 sorted_mask;
4213         guint32 heapt_size = 0;
4214         guint32 meta_size = 256; /* allow for header and other stuff */
4215         guint32 table_offset;
4216         guint32 ntables = 0;
4217         guint64 *int64val;
4218         guint32 *int32val;
4219         guint16 *int16val;
4220         MonoImage *meta;
4221         unsigned char *p;
4222         struct StreamDesc stream_desc [5];
4223
4224         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4225         for (i = 0; i < assembly->gen_params->len; i++){
4226                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4227                 write_generic_param_entry (assembly, entry);
4228         }
4229
4230         stream_desc [0].name  = "#~";
4231         stream_desc [0].stream = &assembly->tstream;
4232         stream_desc [1].name  = "#Strings";
4233         stream_desc [1].stream = &assembly->sheap;
4234         stream_desc [2].name  = "#US";
4235         stream_desc [2].stream = &assembly->us;
4236         stream_desc [3].name  = "#Blob";
4237         stream_desc [3].stream = &assembly->blob;
4238         stream_desc [4].name  = "#GUID";
4239         stream_desc [4].stream = &assembly->guid;
4240         
4241         /* tables that are sorted */
4242         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4243                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4244                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4245                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4246                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4247                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4248                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4249         
4250         /* Compute table sizes */
4251         /* the MonoImage has already been created in mono_image_basic_init() */
4252         meta = &assembly->image;
4253
4254         /* sizes should be multiple of 4 */
4255         pad_heap (&assembly->blob);
4256         pad_heap (&assembly->guid);
4257         pad_heap (&assembly->sheap);
4258         pad_heap (&assembly->us);
4259
4260         /* Setup the info used by compute_sizes () */
4261         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4262         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4263         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4264
4265         meta_size += assembly->blob.index;
4266         meta_size += assembly->guid.index;
4267         meta_size += assembly->sheap.index;
4268         meta_size += assembly->us.index;
4269
4270         for (i=0; i < MONO_TABLE_NUM; ++i)
4271                 meta->tables [i].rows = assembly->tables [i].rows;
4272         
4273         for (i = 0; i < MONO_TABLE_NUM; i++){
4274                 if (meta->tables [i].rows == 0)
4275                         continue;
4276                 valid_mask |= (guint64)1 << i;
4277                 ntables ++;
4278                 meta->tables [i].row_size = mono_metadata_compute_size (
4279                         meta, i, &meta->tables [i].size_bitfield);
4280                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4281         }
4282         heapt_size += 24; /* #~ header size */
4283         heapt_size += ntables * 4;
4284         /* make multiple of 4 */
4285         heapt_size += 3;
4286         heapt_size &= ~3;
4287         meta_size += heapt_size;
4288         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4289         p = (unsigned char*)meta->raw_metadata;
4290         /* the metadata signature */
4291         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4292         /* version numbers and 4 bytes reserved */
4293         int16val = (guint16*)p;
4294         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4295         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4296         p += 8;
4297         /* version string */
4298         int32val = (guint32*)p;
4299         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4300         p += 4;
4301         memcpy (p, meta->version, strlen (meta->version));
4302         p += GUINT32_FROM_LE (*int32val);
4303         align_pointer (meta->raw_metadata, p);
4304         int16val = (guint16*)p;
4305         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4306         *int16val = GUINT16_TO_LE (5); /* number of streams */
4307         p += 4;
4308
4309         /*
4310          * write the stream info.
4311          */
4312         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4313         table_offset += 3; table_offset &= ~3;
4314
4315         assembly->tstream.index = heapt_size;
4316         for (i = 0; i < 5; ++i) {
4317                 int32val = (guint32*)p;
4318                 stream_desc [i].stream->offset = table_offset;
4319                 *int32val++ = GUINT32_TO_LE (table_offset);
4320                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4321                 table_offset += GUINT32_FROM_LE (*int32val);
4322                 table_offset += 3; table_offset &= ~3;
4323                 p += 8;
4324                 strcpy ((char*)p, stream_desc [i].name);
4325                 p += strlen (stream_desc [i].name) + 1;
4326                 align_pointer (meta->raw_metadata, p);
4327         }
4328         /* 
4329          * now copy the data, the table stream header and contents goes first.
4330          */
4331         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4332         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4333         int32val = (guint32*)p;
4334         *int32val = GUINT32_TO_LE (0); /* reserved */
4335         p += 4;
4336
4337         *p++ = 2; /* version */
4338         *p++ = 0;
4339
4340         if (meta->idx_string_wide)
4341                 *p |= 0x01;
4342         if (meta->idx_guid_wide)
4343                 *p |= 0x02;
4344         if (meta->idx_blob_wide)
4345                 *p |= 0x04;
4346         ++p;
4347         *p++ = 1; /* reserved */
4348         int64val = (guint64*)p;
4349         *int64val++ = GUINT64_TO_LE (valid_mask);
4350         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4351         p += 16;
4352         int32val = (guint32*)p;
4353         for (i = 0; i < MONO_TABLE_NUM; i++){
4354                 if (meta->tables [i].rows == 0)
4355                         continue;
4356                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4357         }
4358         p = (unsigned char*)int32val;
4359
4360         /* sort the tables that still need sorting */
4361         table = &assembly->tables [MONO_TABLE_CONSTANT];
4362         if (table->rows)
4363                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4364         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4365         if (table->rows)
4366                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4367         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4368         if (table->rows)
4369                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4370         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4371         if (table->rows)
4372                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4373         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4374         if (table->rows)
4375                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4376         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4377         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4378         if (table->rows)
4379                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4380         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4381         if (table->rows)
4382                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4383
4384         /* compress the tables */
4385         for (i = 0; i < MONO_TABLE_NUM; i++){
4386                 int row, col;
4387                 guint32 *values;
4388                 guint32 bitfield = meta->tables [i].size_bitfield;
4389                 if (!meta->tables [i].rows)
4390                         continue;
4391                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4392                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4393                 meta->tables [i].base = (char*)p;
4394                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4395                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4396                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4397                                 switch (mono_metadata_table_size (bitfield, col)) {
4398                                 case 1:
4399                                         *p++ = values [col];
4400                                         break;
4401                                 case 2:
4402                                         *p++ = values [col] & 0xff;
4403                                         *p++ = (values [col] >> 8) & 0xff;
4404                                         break;
4405                                 case 4:
4406                                         *p++ = values [col] & 0xff;
4407                                         *p++ = (values [col] >> 8) & 0xff;
4408                                         *p++ = (values [col] >> 16) & 0xff;
4409                                         *p++ = (values [col] >> 24) & 0xff;
4410                                         break;
4411                                 default:
4412                                         g_assert_not_reached ();
4413                                 }
4414                         }
4415                 }
4416                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4417         }
4418         
4419         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4420         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4421         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4422         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4423         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4424
4425         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4426 }
4427
4428 /*
4429  * Some tables in metadata need to be sorted according to some criteria, but
4430  * when methods and fields are first created with reflection, they may be assigned a token
4431  * that doesn't correspond to the final token they will get assigned after the sorting.
4432  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4433  * with the reflection objects that represent them. Once all the tables are set up, the 
4434  * reflection objects will contains the correct table index. fixup_method() will fixup the
4435  * tokens for the method with ILGenerator @ilgen.
4436  */
4437 static void
4438 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4439 {
4440         guint32 code_idx = GPOINTER_TO_UINT (value);
4441         MonoReflectionILTokenInfo *iltoken;
4442         MonoReflectionFieldBuilder *field;
4443         MonoReflectionCtorBuilder *ctor;
4444         MonoReflectionMethodBuilder *method;
4445         MonoReflectionTypeBuilder *tb;
4446         MonoReflectionArrayMethod *am;
4447         guint32 i, idx = 0;
4448         unsigned char *target;
4449
4450         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4451                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4452                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4453                 switch (target [3]) {
4454                 case MONO_TABLE_FIELD:
4455                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4456                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4457                                 idx = field->table_idx;
4458                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4459                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4460                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4461                         } else {
4462                                 g_assert_not_reached ();
4463                         }
4464                         break;
4465                 case MONO_TABLE_METHOD:
4466                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4467                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4468                                 idx = method->table_idx;
4469                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4470                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4471                                 idx = ctor->table_idx;
4472                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4473                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4474                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4475                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4476                         } else {
4477                                 g_assert_not_reached ();
4478                         }
4479                         break;
4480                 case MONO_TABLE_TYPEDEF:
4481                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4482                                 g_assert_not_reached ();
4483                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4484                         idx = tb->table_idx;
4485                         break;
4486                 case MONO_TABLE_MEMBERREF:
4487                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4488                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4489                                 idx = am->table_idx;
4490                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4491                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4492                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4493                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4494                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4495                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4496                                 continue;
4497                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4498                                 continue;
4499                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4500                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4501                                 g_assert (is_field_on_inst (f));
4502                                 continue;
4503                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4504                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4505                                 continue;
4506                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4507                                 continue;
4508                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4509                                 continue;
4510                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4511                                 continue;
4512                         } else {
4513                                 g_assert_not_reached ();
4514                         }
4515                         break;
4516                 case MONO_TABLE_METHODSPEC:
4517                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4518                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4519                                 g_assert (mono_method_signature (m)->generic_param_count);
4520                                 continue;
4521                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4522                                 continue;
4523                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4524                                 continue;
4525                         } else {
4526                                 g_assert_not_reached ();
4527                         }
4528                         break;
4529                 default:
4530                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4531                 }
4532                 target [0] = idx & 0xff;
4533                 target [1] = (idx >> 8) & 0xff;
4534                 target [2] = (idx >> 16) & 0xff;
4535         }
4536 }
4537
4538 /*
4539  * fixup_cattrs:
4540  *
4541  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4542  * value is not known when the table is emitted.
4543  */
4544 static void
4545 fixup_cattrs (MonoDynamicImage *assembly)
4546 {
4547         MonoDynamicTable *table;
4548         guint32 *values;
4549         guint32 type, i, idx, token;
4550         MonoObject *ctor;
4551
4552         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4553
4554         for (i = 0; i < table->rows; ++i) {
4555                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4556
4557                 type = values [MONO_CUSTOM_ATTR_TYPE];
4558                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4559                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4560                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4561                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4562                         g_assert (ctor);
4563
4564                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4565                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4566                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4567                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4568                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4569                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4570                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4571                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4572                         }
4573                 }
4574         }
4575 }
4576
4577 static void
4578 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4579 {
4580         MonoDynamicTable *table;
4581         guint32 *values;
4582
4583         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4584         table->rows++;
4585         alloc_table (table, table->rows);
4586         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4587         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4588         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4589         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4590         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4591         table->next_idx++;
4592 }
4593
4594 static void
4595 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4596 {
4597         MonoDynamicTable *table;
4598         guint32 *values;
4599         char blob_size [6];
4600         guchar hash [20];
4601         char *b = blob_size;
4602         char *name, *sname;
4603         guint32 idx, offset;
4604
4605         if (rsrc->filename) {
4606                 name = mono_string_to_utf8 (rsrc->filename);
4607                 sname = g_path_get_basename (name);
4608         
4609                 table = &assembly->tables [MONO_TABLE_FILE];
4610                 table->rows++;
4611                 alloc_table (table, table->rows);
4612                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4613                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4614                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4615                 g_free (sname);
4616
4617                 mono_sha1_get_digest_from_file (name, hash);
4618                 mono_metadata_encode_value (20, b, &b);
4619                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4620                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4621                 g_free (name);
4622                 idx = table->next_idx++;
4623                 rsrc->offset = 0;
4624                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4625         } else {
4626                 char sizebuf [4];
4627                 char *data;
4628                 guint len;
4629                 if (rsrc->data) {
4630                         data = mono_array_addr (rsrc->data, char, 0);
4631                         len = mono_array_length (rsrc->data);
4632                 } else {
4633                         data = NULL;
4634                         len = 0;
4635                 }
4636                 offset = len;
4637                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4638                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4639                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4640                 mono_image_add_stream_data (&assembly->resources, data, len);
4641
4642                 if (!mb->is_main)
4643                         /* 
4644                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4645                          * the main module, but that needs to reference the FILE table
4646                          * which isn't emitted yet.
4647                          */
4648                         return;
4649                 else
4650                         idx = 0;
4651         }
4652
4653         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4654 }
4655
4656 static void
4657 set_version_from_string (MonoString *version, guint32 *values)
4658 {
4659         gchar *ver, *p, *str;
4660         guint32 i;
4661         
4662         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4663         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4664         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4665         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4666         if (!version)
4667                 return;
4668         ver = str = mono_string_to_utf8 (version);
4669         for (i = 0; i < 4; ++i) {
4670                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4671                 switch (*p) {
4672                 case '.':
4673                         p++;
4674                         break;
4675                 case '*':
4676                         /* handle Revision and Build */
4677                         p++;
4678                         break;
4679                 }
4680                 ver = p;
4681         }
4682         g_free (str);
4683 }
4684
4685 static guint32
4686 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4687         gsize len;
4688         guint32 token = 0;
4689         char blob_size [6];
4690         char *b = blob_size;
4691
4692         if (!pkey)
4693                 return token;
4694
4695         len = mono_array_length (pkey);
4696         mono_metadata_encode_value (len, b, &b);
4697         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4698         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4699
4700         assembly->public_key = (guint8 *)g_malloc (len);
4701         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4702         assembly->public_key_len = len;
4703
4704         /* Special case: check for ECMA key (16 bytes) */
4705         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4706                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4707                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4708         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4709                 /* minimum key size (in 2.0) is 384 bits */
4710                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4711         } else {
4712                 /* FIXME - verifier */
4713                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4714                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4715         }
4716         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4717
4718         return token;
4719 }
4720
4721 static void
4722 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4723 {
4724         MonoDynamicTable *table;
4725         MonoDynamicImage *assembly;
4726         MonoReflectionAssemblyBuilder *assemblyb;
4727         MonoDomain *domain;
4728         guint32 *values;
4729         int i;
4730         guint32 module_index;
4731
4732         assemblyb = moduleb->assemblyb;
4733         assembly = moduleb->dynamic_image;
4734         domain = mono_object_domain (assemblyb);
4735
4736         /* Emit ASSEMBLY table */
4737         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4738         alloc_table (table, 1);
4739         values = table->values + MONO_ASSEMBLY_SIZE;
4740         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4741         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4742         if (assemblyb->culture) {
4743                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4744         } else {
4745                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4746         }
4747         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4748         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4749         set_version_from_string (assemblyb->version, values);
4750
4751         /* Emit FILE + EXPORTED_TYPE table */
4752         module_index = 0;
4753         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4754                 int j;
4755                 MonoReflectionModuleBuilder *file_module = 
4756                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4757                 if (file_module != moduleb) {
4758                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4759                         module_index ++;
4760                         if (file_module->types) {
4761                                 for (j = 0; j < file_module->num_types; ++j) {
4762                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4763                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4764                                 }
4765                         }
4766                 }
4767         }
4768         if (assemblyb->loaded_modules) {
4769                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4770                         MonoReflectionModule *file_module = 
4771                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4772                         mono_image_fill_file_table (domain, file_module, assembly);
4773                         module_index ++;
4774                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4775                 }
4776         }
4777         if (assemblyb->type_forwarders)
4778                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4779
4780         /* Emit MANIFESTRESOURCE table */
4781         module_index = 0;
4782         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4783                 int j;
4784                 MonoReflectionModuleBuilder *file_module = 
4785                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4786                 /* The table for the main module is emitted later */
4787                 if (file_module != moduleb) {
4788                         module_index ++;
4789                         if (file_module->resources) {
4790                                 int len = mono_array_length (file_module->resources);
4791                                 for (j = 0; j < len; ++j) {
4792                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4793                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4794                                 }
4795                         }
4796                 }
4797         }               
4798 }
4799
4800 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4801
4802 /*
4803  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4804  * for the modulebuilder @moduleb.
4805  * At the end of the process, method and field tokens are fixed up and the 
4806  * on-disk compressed metadata representation is created.
4807  */
4808 void
4809 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4810 {
4811         MonoDynamicTable *table;
4812         MonoDynamicImage *assembly;
4813         MonoReflectionAssemblyBuilder *assemblyb;
4814         MonoDomain *domain;
4815         MonoPtrArray types;
4816         guint32 *values;
4817         int i, j;
4818
4819         assemblyb = moduleb->assemblyb;
4820         assembly = moduleb->dynamic_image;
4821         domain = mono_object_domain (assemblyb);
4822
4823         if (assembly->text_rva)
4824                 return;
4825
4826         assembly->text_rva = START_TEXT_RVA;
4827
4828         if (moduleb->is_main) {
4829                 mono_image_emit_manifest (moduleb);
4830         }
4831
4832         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4833         table->rows = 1; /* .<Module> */
4834         table->next_idx++;
4835         alloc_table (table, table->rows);
4836         /*
4837          * Set the first entry.
4838          */
4839         values = table->values + table->columns;
4840         values [MONO_TYPEDEF_FLAGS] = 0;
4841         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4842         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4843         values [MONO_TYPEDEF_EXTENDS] = 0;
4844         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4845         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4846
4847         /* 
4848          * handle global methods 
4849          * FIXME: test what to do when global methods are defined in multiple modules.
4850          */
4851         if (moduleb->global_methods) {
4852                 table = &assembly->tables [MONO_TABLE_METHOD];
4853                 table->rows += mono_array_length (moduleb->global_methods);
4854                 alloc_table (table, table->rows);
4855                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4856                         mono_image_get_method_info (
4857                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4858         }
4859         if (moduleb->global_fields) {
4860                 table = &assembly->tables [MONO_TABLE_FIELD];
4861                 table->rows += mono_array_length (moduleb->global_fields);
4862                 alloc_table (table, table->rows);
4863                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4864                         mono_image_get_field_info (
4865                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4866         }
4867
4868         table = &assembly->tables [MONO_TABLE_MODULE];
4869         alloc_table (table, 1);
4870         mono_image_fill_module_table (domain, moduleb, assembly);
4871
4872         /* Collect all types into a list sorted by their table_idx */
4873         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4874
4875         if (moduleb->types)
4876                 for (i = 0; i < moduleb->num_types; ++i) {
4877                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4878                         collect_types (&types, type);
4879                 }
4880
4881         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4882         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4883         table->rows += mono_ptr_array_size (types);
4884         alloc_table (table, table->rows);
4885
4886         /*
4887          * Emit type names + namespaces at one place inside the string heap,
4888          * so load_class_names () needs to touch fewer pages.
4889          */
4890         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4891                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4892                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4893         }
4894         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4895                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4896                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4897         }
4898
4899         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4900                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4901                 mono_image_get_type_info (domain, type, assembly);
4902         }
4903
4904         /* 
4905          * table->rows is already set above and in mono_image_fill_module_table.
4906          */
4907         /* add all the custom attributes at the end, once all the indexes are stable */
4908         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4909
4910         /* CAS assembly permissions */
4911         if (assemblyb->permissions_minimum)
4912                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4913         if (assemblyb->permissions_optional)
4914                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4915         if (assemblyb->permissions_refused)
4916                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4917
4918         module_add_cattrs (assembly, moduleb);
4919
4920         /* fixup tokens */
4921         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4922
4923         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4924          * the final tokens and don't need another fixup pass. */
4925
4926         if (moduleb->global_methods) {
4927                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4928                         MonoReflectionMethodBuilder *mb = mono_array_get (
4929                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4930                         mono_image_add_methodimpl (assembly, mb);
4931                 }
4932         }
4933
4934         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4935                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4936                 if (type->methods) {
4937                         for (j = 0; j < type->num_methods; ++j) {
4938                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4939                                         type->methods, MonoReflectionMethodBuilder*, j);
4940
4941                                 mono_image_add_methodimpl (assembly, mb);
4942                         }
4943                 }
4944         }
4945
4946         mono_ptr_array_destroy (types);
4947
4948         fixup_cattrs (assembly);
4949 }
4950
4951 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4952
4953 void
4954 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4955 {
4956         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4957 }
4958
4959 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4960
4961
4962 typedef struct {
4963         guint32 import_lookup_table;
4964         guint32 timestamp;
4965         guint32 forwarder;
4966         guint32 name_rva;
4967         guint32 import_address_table_rva;
4968 } MonoIDT;
4969
4970 typedef struct {
4971         guint32 name_rva;
4972         guint32 flags;
4973 } MonoILT;
4974
4975 #ifndef DISABLE_REFLECTION_EMIT
4976
4977 /*
4978  * mono_image_insert_string:
4979  * @module: module builder object
4980  * @str: a string
4981  *
4982  * Insert @str into the user string stream of @module.
4983  */
4984 guint32
4985 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4986 {
4987         MonoDynamicImage *assembly;
4988         guint32 idx;
4989         char buf [16];
4990         char *b = buf;
4991         
4992         if (!module->dynamic_image)
4993                 mono_image_module_basic_init (module);
4994
4995         assembly = module->dynamic_image;
4996         
4997         if (assembly->save) {
4998                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4999                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5000 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5001         {
5002                 char *swapped = g_malloc (2 * mono_string_length (str));
5003                 const char *p = (const char*)mono_string_chars (str);
5004
5005                 swap_with_size (swapped, p, 2, mono_string_length (str));
5006                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5007                 g_free (swapped);
5008         }
5009 #else
5010                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5011 #endif
5012                 mono_image_add_stream_data (&assembly->us, "", 1);
5013         } else {
5014                 idx = assembly->us.index ++;
5015         }
5016
5017         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5018
5019         return MONO_TOKEN_STRING | idx;
5020 }
5021
5022 guint32
5023 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
5024 {
5025         MonoClass *klass;
5026         guint32 token = 0;
5027         MonoMethodSignature *sig;
5028
5029         klass = obj->vtable->klass;
5030         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5031                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5032                 MonoMethodSignature *old;
5033                 guint32 sig_token, parent;
5034                 int nargs, i;
5035
5036                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5037
5038                 nargs = mono_array_length (opt_param_types);
5039                 old = mono_method_signature (method);
5040                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5041
5042                 sig->hasthis = old->hasthis;
5043                 sig->explicit_this = old->explicit_this;
5044                 sig->call_convention = old->call_convention;
5045                 sig->generic_param_count = old->generic_param_count;
5046                 sig->param_count = old->param_count + nargs;
5047                 sig->sentinelpos = old->param_count;
5048                 sig->ret = old->ret;
5049
5050                 for (i = 0; i < old->param_count; i++)
5051                         sig->params [i] = old->params [i];
5052
5053                 for (i = 0; i < nargs; i++) {
5054                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5055                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5056                 }
5057
5058                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5059                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5060                 parent >>= MONO_TYPEDEFORREF_BITS;
5061
5062                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5063                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5064
5065                 sig_token = method_encode_signature (assembly, sig);
5066                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5067         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5068                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5069                 ReflectionMethodBuilder rmb;
5070                 guint32 parent, sig_token;
5071                 int nopt_args, nparams, ngparams, i;
5072                 char *name;
5073
5074                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5075                 rmb.opt_types = opt_param_types;
5076                 nopt_args = mono_array_length (opt_param_types);
5077
5078                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5079                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5080                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5081
5082                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5083                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5084                 sig->call_convention = rmb.call_conv;
5085                 sig->generic_param_count = ngparams;
5086                 sig->param_count = nparams + nopt_args;
5087                 sig->sentinelpos = nparams;
5088                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5089
5090                 for (i = 0; i < nparams; i++) {
5091                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5092                         sig->params [i] = mono_reflection_type_get_handle (rt);
5093                 }
5094
5095                 for (i = 0; i < nopt_args; i++) {
5096                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5097                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5098                 }
5099
5100                 sig_token = method_builder_encode_signature (assembly, &rmb);
5101
5102                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5103                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5104
5105                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5106                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5107
5108                 name = mono_string_to_utf8 (rmb.name);
5109                 token = mono_image_get_varargs_method_token (
5110                         assembly, parent, name, sig_token);
5111                 g_free (name);
5112         } else {
5113                 g_error ("requested method token for %s\n", klass->name);
5114         }
5115
5116         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5117         register_dyn_token (assembly, token, obj);
5118         return token;
5119 }
5120
5121 /*
5122  * mono_image_create_token:
5123  * @assembly: a dynamic assembly
5124  * @obj:
5125  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5126  *
5127  * Get a token to insert in the IL code stream for the given MemberInfo.
5128  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5129  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5130  * entry.
5131  */
5132 guint32
5133 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5134                                                  gboolean create_open_instance, gboolean register_token)
5135 {
5136         MonoClass *klass;
5137         guint32 token = 0;
5138
5139         klass = obj->vtable->klass;
5140
5141         /* Check for user defined reflection objects */
5142         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5143         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5144                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5145
5146         if (strcmp (klass->name, "MethodBuilder") == 0) {
5147                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5148                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5149
5150                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5151                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5152                 else
5153                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5154                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5155         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5156                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5157                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5158
5159                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5160                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5161                 else
5162                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5163                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5164         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5165                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5166                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5167                 if (tb->generic_params) {
5168                         token = mono_image_get_generic_field_token (assembly, fb);
5169                 } else {
5170                         if (tb->module->dynamic_image == assembly) {
5171                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5172                         } else {
5173                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5174                         }
5175                 }
5176         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5177                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5178                 if (create_open_instance && tb->generic_params) {
5179                         MonoType *type;
5180                         init_type_builder_generics (obj);
5181                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5182                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5183                         token = mono_metadata_token_from_dor (token);
5184                 } else if (tb->module->dynamic_image == assembly) {
5185                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5186                 } else {
5187                         MonoType *type;
5188                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5189                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5190                 }
5191         } else if (strcmp (klass->name, "MonoType") == 0) {
5192                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5193                 MonoClass *mc = mono_class_from_mono_type (type);
5194                 token = mono_metadata_token_from_dor (
5195                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5196         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5197                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5198                 token = mono_metadata_token_from_dor (
5199                         mono_image_typedef_or_ref (assembly, type));
5200         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5201                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5202                 token = mono_metadata_token_from_dor (
5203                         mono_image_typedef_or_ref (assembly, type));
5204         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5205                    strcmp (klass->name, "MonoMethod") == 0 ||
5206                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5207                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5208                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5209                 if (m->method->is_inflated) {
5210                         if (create_open_instance)
5211                                 token = mono_image_get_methodspec_token (assembly, m->method);
5212                         else
5213                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5214                 } else if ((m->method->klass->image == &assembly->image) &&
5215                          !m->method->klass->generic_class) {
5216                         static guint32 method_table_idx = 0xffffff;
5217                         if (m->method->klass->wastypebuilder) {
5218                                 /* we use the same token as the one that was assigned
5219                                  * to the Methodbuilder.
5220                                  * FIXME: do the equivalent for Fields.
5221                                  */
5222                                 token = m->method->token;
5223                         } else {
5224                                 /*
5225                                  * Each token should have a unique index, but the indexes are
5226                                  * assigned by managed code, so we don't know about them. An
5227                                  * easy solution is to count backwards...
5228                                  */
5229                                 method_table_idx --;
5230                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5231                         }
5232                 } else {
5233                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5234                 }
5235                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5236         } else if (strcmp (klass->name, "MonoField") == 0) {
5237                 MonoReflectionField *f = (MonoReflectionField *)obj;
5238                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5239                         static guint32 field_table_idx = 0xffffff;
5240                         field_table_idx --;
5241                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5242                 } else {
5243                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5244                 }
5245                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5246         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5247                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5248                 token = mono_image_get_array_token (assembly, m);
5249         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5250                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5251                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5252         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5253                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5254                 token = mono_metadata_token_from_dor (
5255                         mono_image_typedef_or_ref (assembly, type));
5256         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5257                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5258                 token = mono_image_get_field_on_inst_token (assembly, f);
5259         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5260                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5261                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5262         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5263                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5264                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5265         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5266                 MonoReflectionType *type = (MonoReflectionType *)obj;
5267                 token = mono_metadata_token_from_dor (
5268                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5269         } else {
5270                 g_error ("requested token for %s\n", klass->name);
5271         }
5272
5273         if (register_token)
5274                 mono_image_register_token (assembly, token, obj);
5275
5276         return token;
5277 }
5278
5279 /*
5280  * mono_image_register_token:
5281  *
5282  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5283  * the Module.ResolveXXXToken () methods to work.
5284  */
5285 void
5286 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5287 {
5288         MonoObject *prev;
5289
5290         dynamic_image_lock (assembly);
5291         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5292         if (prev) {
5293                 /* There could be multiple MethodInfo objects with the same token */
5294                 //g_assert (prev == obj);
5295         } else {
5296                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5297         }
5298         dynamic_image_unlock (assembly);
5299 }
5300
5301 static MonoDynamicImage*
5302 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5303 {
5304         static const guchar entrycode [16] = {0xff, 0x25, 0};
5305         MonoDynamicImage *image;
5306         int i;
5307
5308         const char *version;
5309
5310         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5311                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5312         else
5313                 version = mono_get_runtime_info ()->runtime_version;
5314
5315 #if HAVE_BOEHM_GC
5316         /* The MonoGHashTable's need GC tracking */
5317         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5318 #else
5319         image = g_new0 (MonoDynamicImage, 1);
5320 #endif
5321
5322         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5323         
5324         /*g_print ("created image %p\n", image);*/
5325         /* keep in sync with image.c */
5326         image->image.name = assembly_name;
5327         image->image.assembly_name = image->image.name; /* they may be different */
5328         image->image.module_name = module_name;
5329         image->image.version = g_strdup (version);
5330         image->image.md_version_major = 1;
5331         image->image.md_version_minor = 1;
5332         image->image.dynamic = TRUE;
5333
5334         image->image.references = g_new0 (MonoAssembly*, 1);
5335         image->image.references [0] = NULL;
5336
5337         mono_image_init (&image->image);
5338
5339         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");
5340         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5341         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5342         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5343         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5344         image->handleref = g_hash_table_new (NULL, NULL);
5345         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");
5346         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5347         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");
5348         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");
5349         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5350         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5351         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5352         image->gen_params = g_ptr_array_new ();
5353         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5354
5355         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5356         string_heap_init (&image->sheap);
5357         mono_image_add_stream_data (&image->us, "", 1);
5358         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5359         /* import tables... */
5360         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5361         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5362         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5363         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5364         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5365         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5366         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5367         stream_data_align (&image->code);
5368
5369         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5370
5371         for (i=0; i < MONO_TABLE_NUM; ++i) {
5372                 image->tables [i].next_idx = 1;
5373                 image->tables [i].columns = table_sizes [i];
5374         }
5375
5376         image->image.assembly = (MonoAssembly*)assembly;
5377         image->run = assembly->run;
5378         image->save = assembly->save;
5379         image->pe_kind = 0x1; /* ILOnly */
5380         image->machine = 0x14c; /* I386 */
5381         
5382         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5383
5384         dynamic_images_lock ();
5385
5386         if (!dynamic_images)
5387                 dynamic_images = g_ptr_array_new ();
5388
5389         g_ptr_array_add (dynamic_images, image);
5390
5391         dynamic_images_unlock ();
5392
5393         return image;
5394 }
5395 #endif
5396
5397 static void
5398 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5399 {
5400         g_free (key);
5401 }
5402
5403 static void
5404 release_hashtable (MonoGHashTable **hash)
5405 {
5406         if (*hash) {
5407                 mono_g_hash_table_destroy (*hash);
5408                 *hash = NULL;
5409         }
5410 }
5411
5412 void
5413 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5414 {
5415         release_hashtable (&image->token_fixups);
5416         release_hashtable (&image->handleref_managed);
5417         release_hashtable (&image->tokens);
5418         release_hashtable (&image->remapped_tokens);
5419         release_hashtable (&image->generic_def_objects);
5420         release_hashtable (&image->methodspec);
5421 }
5422
5423 // Free dynamic image pass one: Free resources but not image itself
5424 void
5425 mono_dynamic_image_free (MonoDynamicImage *image)
5426 {
5427         MonoDynamicImage *di = image;
5428         GList *list;
5429         int i;
5430
5431         if (di->methodspec)
5432                 mono_g_hash_table_destroy (di->methodspec);
5433         if (di->typespec)
5434                 g_hash_table_destroy (di->typespec);
5435         if (di->typeref)
5436                 g_hash_table_destroy (di->typeref);
5437         if (di->handleref)
5438                 g_hash_table_destroy (di->handleref);
5439         if (di->handleref_managed)
5440                 mono_g_hash_table_destroy (di->handleref_managed);
5441         if (di->tokens)
5442                 mono_g_hash_table_destroy (di->tokens);
5443         if (di->remapped_tokens)
5444                 mono_g_hash_table_destroy (di->remapped_tokens);
5445         if (di->generic_def_objects)
5446                 mono_g_hash_table_destroy (di->generic_def_objects);
5447         if (di->blob_cache) {
5448                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5449                 g_hash_table_destroy (di->blob_cache);
5450         }
5451         if (di->standalonesig_cache)
5452                 g_hash_table_destroy (di->standalonesig_cache);
5453         for (list = di->array_methods; list; list = list->next) {
5454                 ArrayMethod *am = (ArrayMethod *)list->data;
5455                 g_free (am->sig);
5456                 g_free (am->name);
5457                 g_free (am);
5458         }
5459         g_list_free (di->array_methods);
5460         if (di->gen_params) {
5461                 for (i = 0; i < di->gen_params->len; i++) {
5462                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5463                         mono_gc_deregister_root ((char*) &entry->gparam);
5464                         g_free (entry);
5465                 }
5466                 g_ptr_array_free (di->gen_params, TRUE);
5467         }
5468         if (di->token_fixups)
5469                 mono_g_hash_table_destroy (di->token_fixups);
5470         if (di->method_to_table_idx)
5471                 g_hash_table_destroy (di->method_to_table_idx);
5472         if (di->field_to_table_idx)
5473                 g_hash_table_destroy (di->field_to_table_idx);
5474         if (di->method_aux_hash)
5475                 g_hash_table_destroy (di->method_aux_hash);
5476         if (di->vararg_aux_hash)
5477                 g_hash_table_destroy (di->vararg_aux_hash);
5478         g_free (di->strong_name);
5479         g_free (di->win32_res);
5480         if (di->public_key)
5481                 g_free (di->public_key);
5482
5483         /*g_print ("string heap destroy for image %p\n", di);*/
5484         mono_dynamic_stream_reset (&di->sheap);
5485         mono_dynamic_stream_reset (&di->code);
5486         mono_dynamic_stream_reset (&di->resources);
5487         mono_dynamic_stream_reset (&di->us);
5488         mono_dynamic_stream_reset (&di->blob);
5489         mono_dynamic_stream_reset (&di->tstream);
5490         mono_dynamic_stream_reset (&di->guid);
5491         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5492                 g_free (di->tables [i].values);
5493         }
5494
5495         dynamic_images_lock ();
5496
5497         if (dynamic_images)
5498                 g_ptr_array_remove (dynamic_images, di);
5499
5500         dynamic_images_unlock ();
5501 }
5502
5503 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5504 void
5505 mono_dynamic_image_free_image (MonoDynamicImage *image)
5506 {
5507         /* See create_dynamic_mono_image () */
5508 #if HAVE_BOEHM_GC
5509         /* Allocated using GC_MALLOC */
5510 #else
5511         g_free (image);
5512 #endif
5513 }
5514
5515 #ifndef DISABLE_REFLECTION_EMIT
5516
5517 /*
5518  * mono_image_basic_init:
5519  * @assembly: an assembly builder object
5520  *
5521  * Create the MonoImage that represents the assembly builder and setup some
5522  * of the helper hash table and the basic metadata streams.
5523  */
5524 void
5525 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5526 {
5527         MonoDynamicAssembly *assembly;
5528         MonoDynamicImage *image;
5529         MonoDomain *domain = mono_object_domain (assemblyb);
5530         
5531         if (assemblyb->dynamic_assembly)
5532                 return;
5533
5534 #if HAVE_BOEHM_GC
5535         /* assembly->assembly.image might be GC allocated */
5536         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5537 #else
5538         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5539 #endif
5540
5541         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5542         
5543         assembly->assembly.ref_count = 1;
5544         assembly->assembly.dynamic = TRUE;
5545         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5546         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5547         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5548         if (assemblyb->culture)
5549                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5550         else
5551                 assembly->assembly.aname.culture = g_strdup ("");
5552
5553         if (assemblyb->version) {
5554                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5555                         char **version = g_strsplit (vstr, ".", 4);
5556                         char **parts = version;
5557                         assembly->assembly.aname.major = atoi (*parts++);
5558                         assembly->assembly.aname.minor = atoi (*parts++);
5559                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5560                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5561
5562                         g_strfreev (version);
5563                         g_free (vstr);
5564         } else {
5565                         assembly->assembly.aname.major = 0;
5566                         assembly->assembly.aname.minor = 0;
5567                         assembly->assembly.aname.build = 0;
5568                         assembly->assembly.aname.revision = 0;
5569         }
5570
5571         assembly->run = assemblyb->access != 2;
5572         assembly->save = assemblyb->access != 1;
5573         assembly->domain = domain;
5574
5575         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5576         image->initial_image = TRUE;
5577         assembly->assembly.aname.name = image->image.name;
5578         assembly->assembly.image = &image->image;
5579         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5580                 /* -1 to correct for the trailing NULL byte */
5581                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5582                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5583                 }
5584                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5585         }
5586
5587         mono_domain_assemblies_lock (domain);
5588         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5589         mono_domain_assemblies_unlock (domain);
5590
5591         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5592         
5593         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5594         
5595         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5596 }
5597
5598 #endif /* !DISABLE_REFLECTION_EMIT */
5599
5600 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5601
5602 static int
5603 calc_section_size (MonoDynamicImage *assembly)
5604 {
5605         int nsections = 0;
5606
5607         /* alignment constraints */
5608         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5609         g_assert ((assembly->code.index % 4) == 0);
5610         assembly->meta_size += 3;
5611         assembly->meta_size &= ~3;
5612         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5613         g_assert ((assembly->resources.index % 4) == 0);
5614
5615         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5616         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5617         nsections++;
5618
5619         if (assembly->win32_res) {
5620                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5621
5622                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5623                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5624                 nsections++;
5625         }
5626
5627         assembly->sections [MONO_SECTION_RELOC].size = 12;
5628         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5629         nsections++;
5630
5631         return nsections;
5632 }
5633
5634 typedef struct {
5635         guint32 id;
5636         guint32 offset;
5637         GSList *children;
5638         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5639 } ResTreeNode;
5640
5641 static int
5642 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5643 {
5644         ResTreeNode *t1 = (ResTreeNode*)a;
5645         ResTreeNode *t2 = (ResTreeNode*)b;
5646
5647         return t1->id - t2->id;
5648 }
5649
5650 /*
5651  * resource_tree_create:
5652  *
5653  *  Organize the resources into a resource tree.
5654  */
5655 static ResTreeNode *
5656 resource_tree_create (MonoArray *win32_resources)
5657 {
5658         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5659         GSList *l;
5660         int i;
5661
5662         tree = g_new0 (ResTreeNode, 1);
5663         
5664         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5665                 MonoReflectionWin32Resource *win32_res =
5666                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5667
5668                 /* Create node */
5669
5670                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5671                 lang_node = g_new0 (ResTreeNode, 1);
5672                 lang_node->id = win32_res->lang_id;
5673                 lang_node->win32_res = win32_res;
5674
5675                 /* Create type node if neccesary */
5676                 type_node = NULL;
5677                 for (l = tree->children; l; l = l->next)
5678                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5679                                 type_node = (ResTreeNode*)l->data;
5680                                 break;
5681                         }
5682
5683                 if (!type_node) {
5684                         type_node = g_new0 (ResTreeNode, 1);
5685                         type_node->id = win32_res->res_type;
5686
5687                         /* 
5688                          * The resource types have to be sorted otherwise
5689                          * Windows Explorer can't display the version information.
5690                          */
5691                         tree->children = g_slist_insert_sorted (tree->children, 
5692                                 type_node, resource_tree_compare_by_id);
5693                 }
5694
5695                 /* Create res node if neccesary */
5696                 res_node = NULL;
5697                 for (l = type_node->children; l; l = l->next)
5698                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5699                                 res_node = (ResTreeNode*)l->data;
5700                                 break;
5701                         }
5702
5703                 if (!res_node) {
5704                         res_node = g_new0 (ResTreeNode, 1);
5705                         res_node->id = win32_res->res_id;
5706                         type_node->children = g_slist_append (type_node->children, res_node);
5707                 }
5708
5709                 res_node->children = g_slist_append (res_node->children, lang_node);
5710         }
5711
5712         return tree;
5713 }
5714
5715 /*
5716  * resource_tree_encode:
5717  * 
5718  *   Encode the resource tree into the format used in the PE file.
5719  */
5720 static void
5721 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5722 {
5723         char *entries;
5724         MonoPEResourceDir dir;
5725         MonoPEResourceDirEntry dir_entry;
5726         MonoPEResourceDataEntry data_entry;
5727         GSList *l;
5728         guint32 res_id_entries;
5729
5730         /*
5731          * For the format of the resource directory, see the article
5732          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5733          * Matt Pietrek
5734          */
5735
5736         memset (&dir, 0, sizeof (dir));
5737         memset (&dir_entry, 0, sizeof (dir_entry));
5738         memset (&data_entry, 0, sizeof (data_entry));
5739
5740         g_assert (sizeof (dir) == 16);
5741         g_assert (sizeof (dir_entry) == 8);
5742         g_assert (sizeof (data_entry) == 16);
5743
5744         node->offset = p - begin;
5745
5746         /* IMAGE_RESOURCE_DIRECTORY */
5747         res_id_entries = g_slist_length (node->children);
5748         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5749
5750         memcpy (p, &dir, sizeof (dir));
5751         p += sizeof (dir);
5752
5753         /* Reserve space for entries */
5754         entries = p;
5755         p += sizeof (dir_entry) * res_id_entries;
5756
5757         /* Write children */
5758         for (l = node->children; l; l = l->next) {
5759                 ResTreeNode *child = (ResTreeNode*)l->data;
5760
5761                 if (child->win32_res) {
5762                         guint32 size;
5763
5764                         child->offset = p - begin;
5765
5766                         /* IMAGE_RESOURCE_DATA_ENTRY */
5767                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5768                         size = mono_array_length (child->win32_res->res_data);
5769                         data_entry.rde_size = GUINT32_TO_LE (size);
5770
5771                         memcpy (p, &data_entry, sizeof (data_entry));
5772                         p += sizeof (data_entry);
5773
5774                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5775                         p += size;
5776                 } else {
5777                         resource_tree_encode (child, begin, p, &p);
5778                 }
5779         }
5780
5781         /* IMAGE_RESOURCE_ENTRY */
5782         for (l = node->children; l; l = l->next) {
5783                 ResTreeNode *child = (ResTreeNode*)l->data;
5784
5785                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5786                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5787
5788                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5789                 entries += sizeof (dir_entry);
5790         }
5791
5792         *endbuf = p;
5793 }
5794
5795 static void
5796 resource_tree_free (ResTreeNode * node)
5797 {
5798         GSList * list;
5799         for (list = node->children; list; list = list->next)
5800                 resource_tree_free ((ResTreeNode*)list->data);
5801         g_slist_free(node->children);
5802         g_free (node);
5803 }
5804
5805 static void
5806 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5807 {
5808         char *buf;
5809         char *p;
5810         guint32 size, i;
5811         MonoReflectionWin32Resource *win32_res;
5812         ResTreeNode *tree;
5813
5814         if (!assemblyb->win32_resources)
5815                 return;
5816
5817         /*
5818          * Resources are stored in a three level tree inside the PE file.
5819          * - level one contains a node for each type of resource
5820          * - level two contains a node for each resource
5821          * - level three contains a node for each instance of a resource for a
5822          *   specific language.
5823          */
5824
5825         tree = resource_tree_create (assemblyb->win32_resources);
5826
5827         /* Estimate the size of the encoded tree */
5828         size = 0;
5829         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5830                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5831                 size += mono_array_length (win32_res->res_data);
5832         }
5833         /* Directory structure */
5834         size += mono_array_length (assemblyb->win32_resources) * 256;
5835         p = buf = (char *)g_malloc (size);
5836
5837         resource_tree_encode (tree, p, p, &p);
5838
5839         g_assert (p - buf <= size);
5840
5841         assembly->win32_res = (char *)g_malloc (p - buf);
5842         assembly->win32_res_size = p - buf;
5843         memcpy (assembly->win32_res, buf, p - buf);
5844
5845         g_free (buf);
5846         resource_tree_free (tree);
5847 }
5848
5849 static void
5850 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5851 {
5852         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5853         int i;
5854
5855         p += sizeof (MonoPEResourceDir);
5856         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5857                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5858                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5859                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5860                         fixup_resource_directory (res_section, child, rva);
5861                 } else {
5862                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5863                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5864                 }
5865
5866                 p += sizeof (MonoPEResourceDirEntry);
5867         }
5868 }
5869
5870 static void
5871 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5872 {
5873         guint32 dummy;
5874         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5875                 g_error ("WriteFile returned %d\n", GetLastError ());
5876 }
5877
5878 /*
5879  * mono_image_create_pefile:
5880  * @mb: a module builder object
5881  * 
5882  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5883  * assembly->pefile where it can be easily retrieved later in chunks.
5884  */
5885 void
5886 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5887 {
5888         MonoMSDOSHeader *msdos;
5889         MonoDotNetHeader *header;
5890         MonoSectionTable *section;
5891         MonoCLIHeader *cli_header;
5892         guint32 size, image_size, virtual_base, text_offset;
5893         guint32 header_start, section_start, file_offset, virtual_offset;
5894         MonoDynamicImage *assembly;
5895         MonoReflectionAssemblyBuilder *assemblyb;
5896         MonoDynamicStream pefile_stream = {0};
5897         MonoDynamicStream *pefile = &pefile_stream;
5898         int i, nsections;
5899         guint32 *rva, value;
5900         guchar *p;
5901         static const unsigned char msheader[] = {
5902                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5903                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5904                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5905                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5906                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5907                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5908                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5909                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5910         };
5911
5912         assemblyb = mb->assemblyb;
5913
5914         mono_image_basic_init (assemblyb);
5915         assembly = mb->dynamic_image;
5916
5917         assembly->pe_kind = assemblyb->pe_kind;
5918         assembly->machine = assemblyb->machine;
5919         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5920         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5921         
5922         mono_image_build_metadata (mb);
5923
5924         if (mb->is_main && assemblyb->resources) {
5925                 int len = mono_array_length (assemblyb->resources);
5926                 for (i = 0; i < len; ++i)
5927                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5928         }
5929
5930         if (mb->resources) {
5931                 int len = mono_array_length (mb->resources);
5932                 for (i = 0; i < len; ++i)
5933                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5934         }
5935
5936         build_compressed_metadata (assembly);
5937
5938         if (mb->is_main)
5939                 assembly_add_win32_resources (assembly, assemblyb);
5940
5941         nsections = calc_section_size (assembly);
5942         
5943         /* The DOS header and stub */
5944         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5945         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5946
5947         /* the dotnet header */
5948         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5949
5950         /* the section tables */
5951         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5952
5953         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5954         virtual_offset = VIRT_ALIGN;
5955         image_size = 0;
5956
5957         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5958                 if (!assembly->sections [i].size)
5959                         continue;
5960                 /* align offsets */
5961                 file_offset += FILE_ALIGN - 1;
5962                 file_offset &= ~(FILE_ALIGN - 1);
5963                 virtual_offset += VIRT_ALIGN - 1;
5964                 virtual_offset &= ~(VIRT_ALIGN - 1);
5965
5966                 assembly->sections [i].offset = file_offset;
5967                 assembly->sections [i].rva = virtual_offset;
5968
5969                 file_offset += assembly->sections [i].size;
5970                 virtual_offset += assembly->sections [i].size;
5971                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5972         }
5973
5974         file_offset += FILE_ALIGN - 1;
5975         file_offset &= ~(FILE_ALIGN - 1);
5976
5977         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5978
5979         /* back-patch info */
5980         msdos = (MonoMSDOSHeader*)pefile->data;
5981         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5982
5983         header = (MonoDotNetHeader*)(pefile->data + header_start);
5984         header->pesig [0] = 'P';
5985         header->pesig [1] = 'E';
5986         
5987         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5988         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5989         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5990         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5991         if (assemblyb->pekind == 1) {
5992                 /* it's a dll */
5993                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5994         } else {
5995                 /* it's an exe */
5996                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5997         }
5998
5999         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6000
6001         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6002         header->pe.pe_major = 6;
6003         header->pe.pe_minor = 0;
6004         size = assembly->sections [MONO_SECTION_TEXT].size;
6005         size += FILE_ALIGN - 1;
6006         size &= ~(FILE_ALIGN - 1);
6007         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6008         size = assembly->sections [MONO_SECTION_RSRC].size;
6009         size += FILE_ALIGN - 1;
6010         size &= ~(FILE_ALIGN - 1);
6011         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6012         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6013         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6014         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6015         /* pe_rva_entry_point always at the beginning of the text section */
6016         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6017
6018         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6019         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6020         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6021         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6022         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6023         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6024         size = section_start;
6025         size += FILE_ALIGN - 1;
6026         size &= ~(FILE_ALIGN - 1);
6027         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6028         size = image_size;
6029         size += VIRT_ALIGN - 1;
6030         size &= ~(VIRT_ALIGN - 1);
6031         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6032
6033         /*
6034         // Translate the PEFileKind value to the value expected by the Windows loader
6035         */
6036         {
6037                 short kind;
6038
6039                 /*
6040                 // PEFileKinds.Dll == 1
6041                 // PEFileKinds.ConsoleApplication == 2
6042                 // PEFileKinds.WindowApplication == 3
6043                 //
6044                 // need to get:
6045                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6046                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6047                 */
6048                 if (assemblyb->pekind == 3)
6049                         kind = 2;
6050                 else
6051                         kind = 3;
6052                 
6053                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6054         }    
6055         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6056         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6057         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6058         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6059         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6060         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6061
6062         /* fill data directory entries */
6063
6064         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6065         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6066
6067         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6068         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6069
6070         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6071         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6072         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6073         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6074         /* patch entrypoint name */
6075         if (assemblyb->pekind == 1)
6076                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6077         else
6078                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6079         /* patch imported function RVA name */
6080         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6081         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6082
6083         /* the import table */
6084         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6085         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6086         /* patch imported dll RVA name and other entries in the dir */
6087         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6088         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6089         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6090         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6091         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6092         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6093
6094         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6095         value = (assembly->text_rva + assembly->imp_names_offset);
6096         *p++ = (value) & 0xff;
6097         *p++ = (value >> 8) & (0xff);
6098         *p++ = (value >> 16) & (0xff);
6099         *p++ = (value >> 24) & (0xff);
6100
6101         /* the CLI header info */
6102         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6103         cli_header->ch_size = GUINT32_FROM_LE (72);
6104         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6105         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6106         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6107         if (assemblyb->entry_point) {
6108                 guint32 table_idx = 0;
6109                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6110                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6111                         table_idx = methodb->table_idx;
6112                 } else {
6113                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6114                 }
6115                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6116         } else {
6117                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6118         }
6119         /* The embedded managed resources */
6120         text_offset = assembly->text_rva + assembly->code.index;
6121         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6122         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6123         text_offset += assembly->resources.index;
6124         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6125         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6126         text_offset += assembly->meta_size;
6127         if (assembly->strong_name_size) {
6128                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6129                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6130                 text_offset += assembly->strong_name_size;
6131         }
6132
6133         /* write the section tables and section content */
6134         section = (MonoSectionTable*)(pefile->data + section_start);
6135         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6136                 static const char section_names [][7] = {
6137                         ".text", ".rsrc", ".reloc"
6138                 };
6139                 if (!assembly->sections [i].size)
6140                         continue;
6141                 strcpy (section->st_name, section_names [i]);
6142                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6143                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6144                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6145                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6146                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6147                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6148                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6149                 section ++;
6150         }
6151         
6152         checked_write_file (file, pefile->data, pefile->index);
6153         
6154         mono_dynamic_stream_reset (pefile);
6155         
6156         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6157                 if (!assembly->sections [i].size)
6158                         continue;
6159                 
6160                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6161                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6162                 
6163                 switch (i) {
6164                 case MONO_SECTION_TEXT:
6165                         /* patch entry point */
6166                         p = (guchar*)(assembly->code.data + 2);
6167                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6168                         *p++ = (value) & 0xff;
6169                         *p++ = (value >> 8) & 0xff;
6170                         *p++ = (value >> 16) & 0xff;
6171                         *p++ = (value >> 24) & 0xff;
6172                 
6173                         checked_write_file (file, assembly->code.data, assembly->code.index);
6174                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6175                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6176                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6177                                 
6178
6179                         g_free (assembly->image.raw_metadata);
6180                         break;
6181                 case MONO_SECTION_RELOC: {
6182                         struct {
6183                                 guint32 page_rva;
6184                                 guint32 block_size;
6185                                 guint16 type_and_offset;
6186                                 guint16 term;
6187                         } reloc;
6188                         
6189                         g_assert (sizeof (reloc) == 12);
6190                         
6191                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6192                         reloc.block_size = GUINT32_FROM_LE (12);
6193                         
6194                         /* 
6195                          * the entrypoint is always at the start of the text section 
6196                          * 3 is IMAGE_REL_BASED_HIGHLOW
6197                          * 2 is patch_size_rva - text_rva
6198                          */
6199                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6200                         reloc.term = 0;
6201                         
6202                         checked_write_file (file, &reloc, sizeof (reloc));
6203                         
6204                         break;
6205                 }
6206                 case MONO_SECTION_RSRC:
6207                         if (assembly->win32_res) {
6208
6209                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6210                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6211                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6212                         }
6213                         break;
6214                 default:
6215                         g_assert_not_reached ();
6216                 }
6217         }
6218         
6219         /* check that the file is properly padded */
6220         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6221                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6222         if (! SetEndOfFile (file))
6223                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6224         
6225         mono_dynamic_stream_reset (&assembly->code);
6226         mono_dynamic_stream_reset (&assembly->us);
6227         mono_dynamic_stream_reset (&assembly->blob);
6228         mono_dynamic_stream_reset (&assembly->guid);
6229         mono_dynamic_stream_reset (&assembly->sheap);
6230
6231         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6232         g_hash_table_destroy (assembly->blob_cache);
6233         assembly->blob_cache = NULL;
6234 }
6235
6236 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6237
6238 void
6239 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6240 {
6241         g_assert_not_reached ();
6242 }
6243
6244 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6245
6246 #ifndef DISABLE_REFLECTION_EMIT
6247
6248 MonoReflectionModule *
6249 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6250 {
6251         char *name;
6252         MonoImage *image;
6253         MonoImageOpenStatus status;
6254         MonoDynamicAssembly *assembly;
6255         guint32 module_count;
6256         MonoImage **new_modules;
6257         gboolean *new_modules_loaded;
6258         
6259         name = mono_string_to_utf8 (fileName);
6260
6261         image = mono_image_open (name, &status);
6262         if (!image) {
6263                 MonoException *exc;
6264                 if (status == MONO_IMAGE_ERROR_ERRNO)
6265                         exc = mono_get_exception_file_not_found (fileName);
6266                 else
6267                         exc = mono_get_exception_bad_image_format (name);
6268                 g_free (name);
6269                 mono_raise_exception (exc);
6270         }
6271
6272         g_free (name);
6273
6274         assembly = ab->dynamic_assembly;
6275         image->assembly = (MonoAssembly*)assembly;
6276
6277         module_count = image->assembly->image->module_count;
6278         new_modules = g_new0 (MonoImage *, module_count + 1);
6279         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6280
6281         if (image->assembly->image->modules)
6282                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6283         if (image->assembly->image->modules_loaded)
6284                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6285         new_modules [module_count] = image;
6286         new_modules_loaded [module_count] = TRUE;
6287         mono_image_addref (image);
6288
6289         g_free (image->assembly->image->modules);
6290         image->assembly->image->modules = new_modules;
6291         image->assembly->image->modules_loaded = new_modules_loaded;
6292         image->assembly->image->module_count ++;
6293
6294         mono_assembly_load_references (image, &status);
6295         if (status) {
6296                 mono_image_close (image);
6297                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6298         }
6299
6300         return mono_module_get_object (mono_domain_get (), image);
6301 }
6302
6303 #endif /* DISABLE_REFLECTION_EMIT */
6304
6305 /*
6306  * We need to return always the same object for MethodInfo, FieldInfo etc..
6307  * but we need to consider the reflected type.
6308  * type uses a different hash, since it uses custom hash/equal functions.
6309  */
6310
6311 typedef struct {
6312         gpointer item;
6313         MonoClass *refclass;
6314 } ReflectedEntry;
6315
6316 static gboolean
6317 reflected_equal (gconstpointer a, gconstpointer b) {
6318         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6319         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6320
6321         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6322 }
6323
6324 static guint
6325 reflected_hash (gconstpointer a) {
6326         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6327         return mono_aligned_addr_hash (ea->item);
6328 }
6329
6330 #define CHECK_OBJECT(t,p,k)     \
6331         do {    \
6332                 t _obj; \
6333                 ReflectedEntry e;       \
6334                 e.item = (p);   \
6335                 e.refclass = (k);       \
6336                 mono_domain_lock (domain);      \
6337                 if (!domain->refobject_hash)    \
6338                         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");  \
6339                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6340                         mono_domain_unlock (domain);    \
6341                         return _obj;    \
6342                 }       \
6343         mono_domain_unlock (domain); \
6344         } while (0)
6345
6346 #ifdef HAVE_BOEHM_GC
6347 /* ReflectedEntry doesn't need to be GC tracked */
6348 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6349 #define FREE_REFENTRY(entry) g_free ((entry))
6350 #define REFENTRY_REQUIRES_CLEANUP
6351 #else
6352 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6353 /* FIXME: */
6354 #define FREE_REFENTRY(entry)
6355 #endif
6356
6357 #define CACHE_OBJECT(t,p,o,k)   \
6358         do {    \
6359                 t _obj; \
6360         ReflectedEntry pe; \
6361         pe.item = (p); \
6362         pe.refclass = (k); \
6363         mono_domain_lock (domain); \
6364                 if (!domain->refobject_hash)    \
6365                         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");  \
6366         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6367         if (!_obj) { \
6368                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6369                     e->item = (p);      \
6370                     e->refclass = (k);  \
6371                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6372             _obj = o; \
6373         } \
6374                 mono_domain_unlock (domain);    \
6375         return _obj; \
6376         } while (0)
6377
6378 static void
6379 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6380 {
6381         mono_domain_lock (domain);
6382         if (domain->refobject_hash) {
6383         ReflectedEntry pe;
6384                 gpointer orig_pe, orig_value;
6385
6386                 pe.item = o;
6387                 pe.refclass = klass;
6388                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6389                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6390                         FREE_REFENTRY (orig_pe);
6391                 }
6392         }
6393         mono_domain_unlock (domain);
6394 }
6395
6396 #ifdef REFENTRY_REQUIRES_CLEANUP
6397 static void
6398 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6399 {
6400         FREE_REFENTRY (key);
6401 }
6402 #endif
6403
6404 void
6405 mono_reflection_cleanup_domain (MonoDomain *domain)
6406 {
6407         if (domain->refobject_hash) {
6408 /*let's avoid scanning the whole hashtable if not needed*/
6409 #ifdef REFENTRY_REQUIRES_CLEANUP
6410                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6411 #endif
6412                 mono_g_hash_table_destroy (domain->refobject_hash);
6413                 domain->refobject_hash = NULL;
6414         }
6415 }
6416
6417 #ifndef DISABLE_REFLECTION_EMIT
6418 static gpointer
6419 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6420 {
6421         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6422 }
6423
6424 static gpointer
6425 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6426 {
6427         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6428 }
6429
6430 void
6431 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6432 {
6433         MonoDynamicImage *image = moduleb->dynamic_image;
6434         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6435         if (!image) {
6436                 MonoError error;
6437                 int module_count;
6438                 MonoImage **new_modules;
6439                 MonoImage *ass;
6440                 char *name, *fqname;
6441                 /*
6442                  * FIXME: we already created an image in mono_image_basic_init (), but
6443                  * we don't know which module it belongs to, since that is only 
6444                  * determined at assembly save time.
6445                  */
6446                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6447                 name = mono_string_to_utf8 (ab->name);
6448                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6449                 if (!mono_error_ok (&error)) {
6450                         g_free (name);
6451                         mono_error_raise_exception (&error);
6452                 }
6453                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6454
6455                 moduleb->module.image = &image->image;
6456                 moduleb->dynamic_image = image;
6457                 register_module (mono_object_domain (moduleb), moduleb, image);
6458
6459                 /* register the module with the assembly */
6460                 ass = ab->dynamic_assembly->assembly.image;
6461                 module_count = ass->module_count;
6462                 new_modules = g_new0 (MonoImage *, module_count + 1);
6463
6464                 if (ass->modules)
6465                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6466                 new_modules [module_count] = &image->image;
6467                 mono_image_addref (&image->image);
6468
6469                 g_free (ass->modules);
6470                 ass->modules = new_modules;
6471                 ass->module_count ++;
6472         }
6473 }
6474
6475 void
6476 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6477 {
6478         MonoDynamicImage *image = moduleb->dynamic_image;
6479
6480         g_assert (type->type);
6481         image->wrappers_type = mono_class_from_mono_type (type->type);
6482 }
6483
6484 #endif
6485
6486 /*
6487  * mono_assembly_get_object:
6488  * @domain: an app domain
6489  * @assembly: an assembly
6490  *
6491  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6492  */
6493 MonoReflectionAssembly*
6494 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6495 {
6496         static MonoClass *assembly_type;
6497         MonoReflectionAssembly *res;
6498         
6499         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6500         if (!assembly_type) {
6501                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6502                 if (klass == NULL)
6503                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6504                 g_assert (klass);
6505                 assembly_type = klass;
6506         }
6507         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6508         res->assembly = assembly;
6509
6510         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6511 }
6512
6513
6514
6515 MonoReflectionModule*   
6516 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6517 {
6518         static MonoClass *module_type;
6519         MonoReflectionModule *res;
6520         char* basename;
6521         
6522         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6523         if (!module_type) {
6524                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6525                 if (klass == NULL)
6526                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6527                 g_assert (klass);
6528                 module_type = klass;
6529         }
6530         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6531
6532         res->image = image;
6533         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6534
6535         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6536         basename = g_path_get_basename (image->name);
6537         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6538         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6539         
6540         g_free (basename);
6541
6542         if (image->assembly->image == image) {
6543                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6544         } else {
6545                 int i;
6546                 res->token = 0;
6547                 if (image->assembly->image->modules) {
6548                         for (i = 0; i < image->assembly->image->module_count; i++) {
6549                                 if (image->assembly->image->modules [i] == image)
6550                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6551                         }
6552                         g_assert (res->token);
6553                 }
6554         }
6555
6556         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6557 }
6558
6559 MonoReflectionModule*   
6560 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6561 {
6562         static MonoClass *module_type;
6563         MonoReflectionModule *res;
6564         MonoTableInfo *table;
6565         guint32 cols [MONO_FILE_SIZE];
6566         const char *name;
6567         guint32 i, name_idx;
6568         const char *val;
6569         
6570         if (!module_type) {
6571                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6572                 if (klass == NULL)
6573                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6574                 g_assert (klass);
6575                 module_type = klass;
6576         }
6577         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6578
6579         table = &image->tables [MONO_TABLE_FILE];
6580         g_assert (table_index < table->rows);
6581         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6582
6583         res->image = NULL;
6584         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6585         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6586
6587         /* Check whenever the row has a corresponding row in the moduleref table */
6588         table = &image->tables [MONO_TABLE_MODULEREF];
6589         for (i = 0; i < table->rows; ++i) {
6590                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6591                 val = mono_metadata_string_heap (image, name_idx);
6592                 if (strcmp (val, name) == 0)
6593                         res->image = image->modules [i];
6594         }
6595
6596         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6597         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6598         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6599         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6600         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6601
6602         return res;
6603 }
6604
6605 static gboolean
6606 verify_safe_for_managed_space (MonoType *type)
6607 {
6608         switch (type->type) {
6609 #ifdef DEBUG_HARDER
6610         case MONO_TYPE_ARRAY:
6611                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6612         case MONO_TYPE_PTR:
6613                 return verify_safe_for_managed_space (type->data.type);
6614         case MONO_TYPE_SZARRAY:
6615                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6616         case MONO_TYPE_GENERICINST: {
6617                 MonoGenericInst *inst = type->data.generic_class->inst;
6618                 int i;
6619                 if (!inst->is_open)
6620                         break;
6621                 for (i = 0; i < inst->type_argc; ++i)
6622                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6623                                 return FALSE;
6624                 return TRUE;
6625         }
6626 #endif
6627         case MONO_TYPE_VAR:
6628         case MONO_TYPE_MVAR:
6629                 return TRUE;
6630         default:
6631                 return TRUE;
6632         }
6633 }
6634
6635 static MonoType*
6636 mono_type_normalize (MonoType *type)
6637 {
6638         int i;
6639         MonoGenericClass *gclass;
6640         MonoGenericInst *ginst;
6641         MonoClass *gtd;
6642         MonoGenericContainer *gcontainer;
6643         MonoType **argv = NULL;
6644         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6645
6646         if (type->type != MONO_TYPE_GENERICINST)
6647                 return type;
6648
6649         gclass = type->data.generic_class;
6650         ginst = gclass->context.class_inst;
6651         if (!ginst->is_open)
6652                 return type;
6653
6654         gtd = gclass->container_class;
6655         gcontainer = gtd->generic_container;
6656         argv = g_newa (MonoType*, ginst->type_argc);
6657
6658         for (i = 0; i < ginst->type_argc; ++i) {
6659                 MonoType *t = ginst->type_argv [i], *norm;
6660                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6661                         is_denorm_gtd = FALSE;
6662                 norm = mono_type_normalize (t);
6663                 argv [i] = norm;
6664                 if (norm != t)
6665                         requires_rebind = TRUE;
6666         }
6667
6668         if (is_denorm_gtd)
6669                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6670
6671         if (requires_rebind) {
6672                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6673                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6674         }
6675
6676         return type;
6677 }
6678 /*
6679  * mono_type_get_object:
6680  * @domain: an app domain
6681  * @type: a type
6682  *
6683  * Return an System.MonoType object representing the type @type.
6684  */
6685 MonoReflectionType*
6686 mono_type_get_object (MonoDomain *domain, MonoType *type)
6687 {
6688         MonoError error;
6689         MonoType *norm_type;
6690         MonoReflectionType *res;
6691         MonoClass *klass = mono_class_from_mono_type (type);
6692
6693         /*we must avoid using @type as it might have come
6694          * from a mono_metadata_type_dup and the caller
6695          * expects that is can be freed.
6696          * Using the right type from 
6697          */
6698         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6699
6700         /* void is very common */
6701         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6702                 return (MonoReflectionType*)domain->typeof_void;
6703
6704         /*
6705          * If the vtable of the given class was already created, we can use
6706          * the MonoType from there and avoid all locking and hash table lookups.
6707          * 
6708          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6709          * that the resulting object is different.   
6710          */
6711         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6712                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6713                 if (vtable && vtable->type)
6714                         return (MonoReflectionType *)vtable->type;
6715         }
6716
6717         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6718         mono_domain_lock (domain);
6719         if (!domain->type_hash)
6720                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6721                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6722         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6723                 mono_domain_unlock (domain);
6724                 mono_loader_unlock ();
6725                 return res;
6726         }
6727
6728         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6729          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6730          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6731          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6732          * artifact of how generics are encoded and should be transparent to managed code so we
6733          * need to weed out this diference when retrieving managed System.Type objects.
6734          */
6735         norm_type = mono_type_normalize (type);
6736         if (norm_type != type) {
6737                 res = mono_type_get_object (domain, norm_type);
6738                 mono_g_hash_table_insert (domain->type_hash, type, res);
6739                 mono_domain_unlock (domain);
6740                 mono_loader_unlock ();
6741                 return res;
6742         }
6743
6744         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6745         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6746                 g_assert (0);
6747
6748         if (!verify_safe_for_managed_space (type)) {
6749                 mono_domain_unlock (domain);
6750                 mono_loader_unlock ();
6751                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6752         }
6753
6754         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6755                 gboolean is_type_done = TRUE;
6756                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6757                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6758                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6759                 */
6760                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6761                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6762
6763                         if (gparam->owner && gparam->owner->is_method) {
6764                                 MonoMethod *method = gparam->owner->owner.method;
6765                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6766                                         is_type_done = FALSE;
6767                         } else if (gparam->owner && !gparam->owner->is_method) {
6768                                 MonoClass *klass = gparam->owner->owner.klass;
6769                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6770                                         is_type_done = FALSE;
6771                         }
6772                 } 
6773
6774                 /* g_assert_not_reached (); */
6775                 /* should this be considered an error condition? */
6776                 if (is_type_done && !type->byref) {
6777                         mono_domain_unlock (domain);
6778                         mono_loader_unlock ();
6779                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
6780                 }
6781         }
6782         /* This is stored in vtables/JITted code so it has to be pinned */
6783         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, &error);
6784         mono_error_raise_exception (&error);
6785         res->type = type;
6786         mono_g_hash_table_insert (domain->type_hash, type, res);
6787
6788         if (type->type == MONO_TYPE_VOID)
6789                 domain->typeof_void = (MonoObject*)res;
6790
6791         mono_domain_unlock (domain);
6792         mono_loader_unlock ();
6793         return res;
6794 }
6795
6796 /*
6797  * mono_method_get_object:
6798  * @domain: an app domain
6799  * @method: a method
6800  * @refclass: the reflected type (can be NULL)
6801  *
6802  * Return an System.Reflection.MonoMethod object representing the method @method.
6803  */
6804 MonoReflectionMethod*
6805 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6806 {
6807         /*
6808          * We use the same C representation for methods and constructors, but the type 
6809          * name in C# is different.
6810          */
6811         static MonoClass *System_Reflection_MonoMethod = NULL;
6812         static MonoClass *System_Reflection_MonoCMethod = NULL;
6813         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6814         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6815         MonoClass *klass;
6816         MonoReflectionMethod *ret;
6817
6818         if (method->is_inflated) {
6819                 MonoReflectionGenericMethod *gret;
6820
6821                 if (!refclass)
6822                         refclass = method->klass;
6823                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6824                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6825                         if (!System_Reflection_MonoGenericCMethod)
6826                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6827                         klass = System_Reflection_MonoGenericCMethod;
6828                 } else {
6829                         if (!System_Reflection_MonoGenericMethod)
6830                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6831                         klass = System_Reflection_MonoGenericMethod;
6832                 }
6833                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6834                 gret->method.method = method;
6835                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6836                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6837                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6838         }
6839
6840         if (!refclass)
6841                 refclass = method->klass;
6842
6843         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6844         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6845                 if (!System_Reflection_MonoCMethod)
6846                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6847                 klass = System_Reflection_MonoCMethod;
6848         }
6849         else {
6850                 if (!System_Reflection_MonoMethod)
6851                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6852                 klass = System_Reflection_MonoMethod;
6853         }
6854         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6855         ret->method = method;
6856         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6857         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6858 }
6859
6860 /*
6861  * mono_method_clear_object:
6862  *
6863  *   Clear the cached reflection objects for the dynamic method METHOD.
6864  */
6865 void
6866 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6867 {
6868         MonoClass *klass;
6869         g_assert (method_is_dynamic (method));
6870
6871         klass = method->klass;
6872         while (klass) {
6873                 clear_cached_object (domain, method, klass);
6874                 klass = klass->parent;
6875         }
6876         /* Added by mono_param_get_objects () */
6877         clear_cached_object (domain, &(method->signature), NULL);
6878         klass = method->klass;
6879         while (klass) {
6880                 clear_cached_object (domain, &(method->signature), klass);
6881                 klass = klass->parent;
6882         }
6883 }
6884
6885 /*
6886  * mono_field_get_object:
6887  * @domain: an app domain
6888  * @klass: a type
6889  * @field: a field
6890  *
6891  * Return an System.Reflection.MonoField object representing the field @field
6892  * in class @klass.
6893  */
6894 MonoReflectionField*
6895 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6896 {
6897         MonoReflectionField *res;
6898         static MonoClass *monofield_klass;
6899
6900         CHECK_OBJECT (MonoReflectionField *, field, klass);
6901         if (!monofield_klass)
6902                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6903         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6904         res->klass = klass;
6905         res->field = field;
6906         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6907
6908         if (is_field_on_inst (field)) {
6909                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6910                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6911         } else {
6912                 if (field->type)
6913                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6914                 res->attrs = mono_field_get_flags (field);
6915         }
6916         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6917 }
6918
6919 /*
6920  * mono_property_get_object:
6921  * @domain: an app domain
6922  * @klass: a type
6923  * @property: a property
6924  *
6925  * Return an System.Reflection.MonoProperty object representing the property @property
6926  * in class @klass.
6927  */
6928 MonoReflectionProperty*
6929 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6930 {
6931         MonoReflectionProperty *res;
6932         static MonoClass *monoproperty_klass;
6933
6934         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6935         if (!monoproperty_klass)
6936                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6937         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6938         res->klass = klass;
6939         res->property = property;
6940         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6941 }
6942
6943 /*
6944  * mono_event_get_object:
6945  * @domain: an app domain
6946  * @klass: a type
6947  * @event: a event
6948  *
6949  * Return an System.Reflection.MonoEvent object representing the event @event
6950  * in class @klass.
6951  */
6952 MonoReflectionEvent*
6953 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6954 {
6955         MonoReflectionEvent *res;
6956         MonoReflectionMonoEvent *mono_event;
6957         static MonoClass *monoevent_klass;
6958
6959         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6960         if (!monoevent_klass)
6961                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6962         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6963         mono_event->klass = klass;
6964         mono_event->event = event;
6965         res = (MonoReflectionEvent*)mono_event;
6966         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6967 }
6968
6969 /**
6970  * mono_get_reflection_missing_object:
6971  * @domain: Domain where the object lives
6972  *
6973  * Returns the System.Reflection.Missing.Value singleton object
6974  * (of type System.Reflection.Missing).
6975  *
6976  * Used as the value for ParameterInfo.DefaultValue when Optional
6977  * is present
6978  */
6979 static MonoObject *
6980 mono_get_reflection_missing_object (MonoDomain *domain)
6981 {
6982         MonoObject *obj;
6983         static MonoClassField *missing_value_field = NULL;
6984         
6985         if (!missing_value_field) {
6986                 MonoClass *missing_klass;
6987                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6988                 mono_class_init (missing_klass);
6989                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6990                 g_assert (missing_value_field);
6991         }
6992         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6993         g_assert (obj);
6994         return obj;
6995 }
6996
6997 static MonoObject*
6998 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6999 {
7000         if (!*dbnull)
7001                 *dbnull = mono_get_dbnull_object (domain);
7002         return *dbnull;
7003 }
7004
7005 static MonoObject*
7006 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7007 {
7008         if (!*reflection_missing)
7009                 *reflection_missing = mono_get_reflection_missing_object (domain);
7010         return *reflection_missing;
7011 }
7012
7013 /*
7014  * mono_param_get_objects:
7015  * @domain: an app domain
7016  * @method: a method
7017  *
7018  * Return an System.Reflection.ParameterInfo array object representing the parameters
7019  * in the method @method.
7020  */
7021 MonoArray*
7022 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7023 {
7024         static MonoClass *System_Reflection_ParameterInfo;
7025         static MonoClass *System_Reflection_ParameterInfo_array;
7026         MonoError error;
7027         MonoArray *res = NULL;
7028         MonoReflectionMethod *member = NULL;
7029         MonoReflectionParameter *param = NULL;
7030         char **names, **blobs = NULL;
7031         guint32 *types = NULL;
7032         MonoType *type = NULL;
7033         MonoObject *dbnull = NULL;
7034         MonoObject *missing = NULL;
7035         MonoMarshalSpec **mspecs;
7036         MonoMethodSignature *sig;
7037         MonoVTable *pinfo_vtable;
7038         int i;
7039
7040         if (!System_Reflection_ParameterInfo_array) {
7041                 MonoClass *klass;
7042
7043                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
7044                 if (!klass)
7045                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
7046
7047                 mono_memory_barrier ();
7048                 System_Reflection_ParameterInfo = klass; 
7049
7050         
7051                 klass = mono_array_class_get (klass, 1);
7052                 mono_memory_barrier ();
7053                 System_Reflection_ParameterInfo_array = klass;
7054         }
7055
7056         sig = mono_method_signature_checked (method, &error);
7057         if (!mono_error_ok (&error))
7058                 mono_error_raise_exception (&error);
7059
7060         if (!sig->param_count) {
7061                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7062                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7063
7064                 return res;
7065         }
7066
7067         /* Note: the cache is based on the address of the signature into the method
7068          * since we already cache MethodInfos with the method as keys.
7069          */
7070         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7071
7072         member = mono_method_get_object (domain, method, refclass);
7073         names = g_new (char *, sig->param_count);
7074         mono_method_get_param_names (method, (const char **) names);
7075
7076         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7077         mono_method_get_marshal_info (method, mspecs);
7078
7079         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7080         mono_error_raise_exception (&error); /* FIXME don't raise here */
7081
7082         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7083         for (i = 0; i < sig->param_count; ++i) {
7084                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7085                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7086                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7087                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7088                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7089                 param->PositionImpl = i;
7090                 param->AttrsImpl = sig->params [i]->attrs;
7091
7092                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7093                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7094                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7095                         else
7096                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7097                 } else {
7098
7099                         if (!blobs) {
7100                                 blobs = g_new0 (char *, sig->param_count);
7101                                 types = g_new0 (guint32, sig->param_count);
7102                                 get_default_param_value_blobs (method, blobs, types); 
7103                         }
7104
7105                         /* Build MonoType for the type from the Constant Table */
7106                         if (!type)
7107                                 type = g_new0 (MonoType, 1);
7108                         type->type = (MonoTypeEnum)types [i];
7109                         type->data.klass = NULL;
7110                         if (types [i] == MONO_TYPE_CLASS)
7111                                 type->data.klass = mono_defaults.object_class;
7112                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7113                                 /* For enums, types [i] contains the base type */
7114
7115                                         type->type = MONO_TYPE_VALUETYPE;
7116                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7117                         } else
7118                                 type->data.klass = mono_class_from_mono_type (type);
7119
7120                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7121
7122                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7123                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7124                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7125                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7126                                 else
7127                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7128                         }
7129                         
7130                 }
7131
7132                 if (mspecs [i + 1])
7133                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7134                 
7135                 mono_array_setref (res, i, param);
7136         }
7137         g_free (names);
7138         g_free (blobs);
7139         g_free (types);
7140         g_free (type);
7141
7142         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7143                 if (mspecs [i])
7144                         mono_metadata_free_marshal_spec (mspecs [i]);
7145         g_free (mspecs);
7146         
7147         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7148 }
7149
7150 MonoArray*
7151 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7152 {
7153         return mono_param_get_objects_internal (domain, method, NULL);
7154 }
7155
7156 /*
7157  * mono_method_body_get_object:
7158  * @domain: an app domain
7159  * @method: a method
7160  *
7161  * Return an System.Reflection.MethodBody object representing the method @method.
7162  */
7163 MonoReflectionMethodBody*
7164 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7165 {
7166         static MonoClass *System_Reflection_MethodBody = NULL;
7167         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7168         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7169         MonoReflectionMethodBody *ret;
7170         MonoMethodHeader *header;
7171         MonoImage *image;
7172         guint32 method_rva, local_var_sig_token;
7173     char *ptr;
7174         unsigned char format, flags;
7175         int i;
7176
7177         /* for compatibility with .net */
7178     if (method_is_dynamic (method))
7179         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7180
7181         if (!System_Reflection_MethodBody)
7182                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7183         if (!System_Reflection_LocalVariableInfo)
7184                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7185         if (!System_Reflection_ExceptionHandlingClause)
7186                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7187
7188         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7189
7190         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7191                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7192             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7193                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7194             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7195                 return NULL;
7196
7197         image = method->klass->image;
7198         header = mono_method_get_header (method);
7199
7200         if (!image_is_dynamic (image)) {
7201                 /* Obtain local vars signature token */
7202                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7203                 ptr = mono_image_rva_map (image, method_rva);
7204                 flags = *(const unsigned char *) ptr;
7205                 format = flags & METHOD_HEADER_FORMAT_MASK;
7206                 switch (format){
7207                 case METHOD_HEADER_TINY_FORMAT:
7208                         local_var_sig_token = 0;
7209                         break;
7210                 case METHOD_HEADER_FAT_FORMAT:
7211                         ptr += 2;
7212                         ptr += 2;
7213                         ptr += 4;
7214                         local_var_sig_token = read32 (ptr);
7215                         break;
7216                 default:
7217                         g_assert_not_reached ();
7218                 }
7219         } else
7220                 local_var_sig_token = 0; //FIXME
7221
7222         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7223
7224         ret->init_locals = header->init_locals;
7225         ret->max_stack = header->max_stack;
7226         ret->local_var_sig_token = local_var_sig_token;
7227         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7228         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7229
7230         /* Locals */
7231         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7232         for (i = 0; i < header->num_locals; ++i) {
7233                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7234                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7235                 info->is_pinned = header->locals [i]->pinned;
7236                 info->local_index = i;
7237                 mono_array_setref (ret->locals, i, info);
7238         }
7239
7240         /* Exceptions */
7241         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7242         for (i = 0; i < header->num_clauses; ++i) {
7243                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7244                 MonoExceptionClause *clause = &header->clauses [i];
7245
7246                 info->flags = clause->flags;
7247                 info->try_offset = clause->try_offset;
7248                 info->try_length = clause->try_len;
7249                 info->handler_offset = clause->handler_offset;
7250                 info->handler_length = clause->handler_len;
7251                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7252                         info->filter_offset = clause->data.filter_offset;
7253                 else if (clause->data.catch_class)
7254                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7255
7256                 mono_array_setref (ret->clauses, i, info);
7257         }
7258
7259         mono_metadata_free_mh (header);
7260         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7261         return ret;
7262 }
7263
7264 /**
7265  * mono_get_dbnull_object:
7266  * @domain: Domain where the object lives
7267  *
7268  * Returns the System.DBNull.Value singleton object
7269  *
7270  * Used as the value for ParameterInfo.DefaultValue 
7271  */
7272 MonoObject *
7273 mono_get_dbnull_object (MonoDomain *domain)
7274 {
7275         MonoObject *obj;
7276         static MonoClassField *dbnull_value_field = NULL;
7277         
7278         if (!dbnull_value_field) {
7279                 MonoClass *dbnull_klass;
7280                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7281                 mono_class_init (dbnull_klass);
7282                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7283                 g_assert (dbnull_value_field);
7284         }
7285         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7286         g_assert (obj);
7287         return obj;
7288 }
7289
7290 static void
7291 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7292 {
7293         guint32 param_index, i, lastp, crow = 0;
7294         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7295         gint32 idx;
7296
7297         MonoClass *klass = method->klass;
7298         MonoImage *image = klass->image;
7299         MonoMethodSignature *methodsig = mono_method_signature (method);
7300
7301         MonoTableInfo *constt;
7302         MonoTableInfo *methodt;
7303         MonoTableInfo *paramt;
7304
7305         if (!methodsig->param_count)
7306                 return;
7307
7308         mono_class_init (klass);
7309
7310         if (image_is_dynamic (klass->image)) {
7311                 MonoReflectionMethodAux *aux;
7312                 if (method->is_inflated)
7313                         method = ((MonoMethodInflated*)method)->declaring;
7314                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7315                 if (aux && aux->param_defaults) {
7316                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7317                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7318                 }
7319                 return;
7320         }
7321
7322         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7323         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7324         constt = &image->tables [MONO_TABLE_CONSTANT];
7325
7326         idx = mono_method_get_index (method) - 1;
7327         g_assert (idx != -1);
7328
7329         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7330         if (idx + 1 < methodt->rows)
7331                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7332         else
7333                 lastp = paramt->rows + 1;
7334
7335         for (i = param_index; i < lastp; ++i) {
7336                 guint32 paramseq;
7337
7338                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7339                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7340
7341                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7342                         continue;
7343
7344                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7345                 if (!crow) {
7346                         continue;
7347                 }
7348         
7349                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7350                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7351                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7352         }
7353
7354         return;
7355 }
7356
7357 MonoObject *
7358 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7359 {
7360         void *retval;
7361         MonoClass *klass;
7362         MonoObject *object;
7363         MonoType *basetype = type;
7364
7365         if (!blob)
7366                 return NULL;
7367         
7368         klass = mono_class_from_mono_type (type);
7369         if (klass->valuetype) {
7370                 object = mono_object_new (domain, klass);
7371                 retval = ((gchar *) object + sizeof (MonoObject));
7372                 if (klass->enumtype)
7373                         basetype = mono_class_enum_basetype (klass);
7374         } else {
7375                 retval = &object;
7376         }
7377                         
7378         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7379                 return object;
7380         else
7381                 return NULL;
7382 }
7383
7384 static int
7385 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7386         int found_sep;
7387         char *s;
7388         gboolean quoted = FALSE;
7389
7390         memset (assembly, 0, sizeof (MonoAssemblyName));
7391         assembly->culture = "";
7392         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7393
7394         if (*p == '"') {
7395                 quoted = TRUE;
7396                 p++;
7397         }
7398         assembly->name = p;
7399         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7400                 p++;
7401         if (quoted) {
7402                 if (*p != '"')
7403                         return 1;
7404                 *p = 0;
7405                 p++;
7406         }
7407         if (*p != ',')
7408                 return 1;
7409         *p = 0;
7410         /* Remove trailing whitespace */
7411         s = p - 1;
7412         while (*s && g_ascii_isspace (*s))
7413                 *s-- = 0;
7414         p ++;
7415         while (g_ascii_isspace (*p))
7416                 p++;
7417         while (*p) {
7418                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7419                         p += 8;
7420                         assembly->major = strtoul (p, &s, 10);
7421                         if (s == p || *s != '.')
7422                                 return 1;
7423                         p = ++s;
7424                         assembly->minor = strtoul (p, &s, 10);
7425                         if (s == p || *s != '.')
7426                                 return 1;
7427                         p = ++s;
7428                         assembly->build = strtoul (p, &s, 10);
7429                         if (s == p || *s != '.')
7430                                 return 1;
7431                         p = ++s;
7432                         assembly->revision = strtoul (p, &s, 10);
7433                         if (s == p)
7434                                 return 1;
7435                         p = s;
7436                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7437                         p += 8;
7438                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7439                                 assembly->culture = "";
7440                                 p += 7;
7441                         } else {
7442                                 assembly->culture = p;
7443                                 while (*p && *p != ',') {
7444                                         p++;
7445                                 }
7446                         }
7447                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7448                         p += 15;
7449                         if (strncmp (p, "null", 4) == 0) {
7450                                 p += 4;
7451                         } else {
7452                                 int len;
7453                                 gchar *start = p;
7454                                 while (*p && *p != ',') {
7455                                         p++;
7456                                 }
7457                                 len = (p - start + 1);
7458                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7459                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7460                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7461                         }
7462                 } else {
7463                         while (*p && *p != ',')
7464                                 p++;
7465                 }
7466                 found_sep = 0;
7467                 while (g_ascii_isspace (*p) || *p == ',') {
7468                         *p++ = 0;
7469                         found_sep = 1;
7470                         continue;
7471                 }
7472                 /* failed */
7473                 if (!found_sep)
7474                         return 1;
7475         }
7476
7477         return 0;
7478 }
7479
7480 /*
7481  * mono_reflection_parse_type:
7482  * @name: type name
7483  *
7484  * Parse a type name as accepted by the GetType () method and output the info
7485  * extracted in the info structure.
7486  * the name param will be mangled, so, make a copy before passing it to this function.
7487  * The fields in info will be valid until the memory pointed to by name is valid.
7488  *
7489  * See also mono_type_get_name () below.
7490  *
7491  * Returns: 0 on parse error.
7492  */
7493 static int
7494 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7495                              MonoTypeNameParse *info)
7496 {
7497         char *start, *p, *w, *last_point, *startn;
7498         int in_modifiers = 0;
7499         int isbyref = 0, rank = 0, isptr = 0;
7500
7501         start = p = w = name;
7502
7503         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7504         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7505         info->name = info->name_space = NULL;
7506         info->nested = NULL;
7507         info->modifiers = NULL;
7508         info->type_arguments = NULL;
7509
7510         /* last_point separates the namespace from the name */
7511         last_point = NULL;
7512         /* Skips spaces */
7513         while (*p == ' ') p++, start++, w++, name++;
7514
7515         while (*p) {
7516                 switch (*p) {
7517                 case '+':
7518                         *p = 0; /* NULL terminate the name */
7519                         startn = p + 1;
7520                         info->nested = g_list_append (info->nested, startn);
7521                         /* we have parsed the nesting namespace + name */
7522                         if (info->name)
7523                                 break;
7524                         if (last_point) {
7525                                 info->name_space = start;
7526                                 *last_point = 0;
7527                                 info->name = last_point + 1;
7528                         } else {
7529                                 info->name_space = (char *)"";
7530                                 info->name = start;
7531                         }
7532                         break;
7533                 case '.':
7534                         last_point = p;
7535                         break;
7536                 case '\\':
7537                         ++p;
7538                         break;
7539                 case '&':
7540                 case '*':
7541                 case '[':
7542                 case ',':
7543                 case ']':
7544                         in_modifiers = 1;
7545                         break;
7546                 default:
7547                         break;
7548                 }
7549                 if (in_modifiers)
7550                         break;
7551                 // *w++ = *p++;
7552                 p++;
7553         }
7554         
7555         if (!info->name) {
7556                 if (last_point) {
7557                         info->name_space = start;
7558                         *last_point = 0;
7559                         info->name = last_point + 1;
7560                 } else {
7561                         info->name_space = (char *)"";
7562                         info->name = start;
7563                 }
7564         }
7565         while (*p) {
7566                 switch (*p) {
7567                 case '&':
7568                         if (isbyref) /* only one level allowed by the spec */
7569                                 return 0;
7570                         isbyref = 1;
7571                         isptr = 0;
7572                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7573                         *p++ = 0;
7574                         break;
7575                 case '*':
7576                         if (isbyref) /* pointer to ref not okay */
7577                                 return 0;
7578                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7579                         isptr = 1;
7580                         *p++ = 0;
7581                         break;
7582                 case '[':
7583                         if (isbyref) /* array of ref and generic ref are not okay */
7584                                 return 0;
7585                         //Decide if it's an array of a generic argument list
7586                         *p++ = 0;
7587
7588                         if (!*p) //XXX test
7589                                 return 0;
7590                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7591                                 isptr = 0;
7592                                 rank = 1;
7593                                 while (*p) {
7594                                         if (*p == ']')
7595                                                 break;
7596                                         if (*p == ',')
7597                                                 rank++;
7598                                         else if (*p == '*') /* '*' means unknown lower bound */
7599                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7600                                         else
7601                                                 return 0;
7602                                         ++p;
7603                                 }
7604                                 if (*p++ != ']')
7605                                         return 0;
7606                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7607                         } else {
7608                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7609                                         return 0;
7610                                 isptr = 0;
7611                                 info->type_arguments = g_ptr_array_new ();
7612                                 while (*p) {
7613                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7614                                         gboolean fqname = FALSE;
7615
7616                                         g_ptr_array_add (info->type_arguments, subinfo);
7617
7618                                         while (*p == ' ') p++;
7619                                         if (*p == '[') {
7620                                                 p++;
7621                                                 fqname = TRUE;
7622                                         }
7623
7624                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7625                                                 return 0;
7626
7627                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7628                                         if (fqname && (*p != ']')) {
7629                                                 char *aname;
7630
7631                                                 if (*p != ',')
7632                                                         return 0;
7633                                                 *p++ = 0;
7634
7635                                                 aname = p;
7636                                                 while (*p && (*p != ']'))
7637                                                         p++;
7638
7639                                                 if (*p != ']')
7640                                                         return 0;
7641
7642                                                 *p++ = 0;
7643                                                 while (*aname) {
7644                                                         if (g_ascii_isspace (*aname)) {
7645                                                                 ++aname;
7646                                                                 continue;
7647                                                         }
7648                                                         break;
7649                                                 }
7650                                                 if (!*aname ||
7651                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7652                                                         return 0;
7653                                         } else if (fqname && (*p == ']')) {
7654                                                 *p++ = 0;
7655                                         }
7656                                         if (*p == ']') {
7657                                                 *p++ = 0;
7658                                                 break;
7659                                         } else if (!*p) {
7660                                                 return 0;
7661                                         }
7662                                         *p++ = 0;
7663                                 }
7664                         }
7665                         break;
7666                 case ']':
7667                         if (is_recursed)
7668                                 goto end;
7669                         return 0;
7670                 case ',':
7671                         if (is_recursed)
7672                                 goto end;
7673                         *p++ = 0;
7674                         while (*p) {
7675                                 if (g_ascii_isspace (*p)) {
7676                                         ++p;
7677                                         continue;
7678                                 }
7679                                 break;
7680                         }
7681                         if (!*p)
7682                                 return 0; /* missing assembly name */
7683                         if (!assembly_name_to_aname (&info->assembly, p))
7684                                 return 0;
7685                         break;
7686                 default:
7687                         return 0;
7688                 }
7689                 if (info->assembly.name)
7690                         break;
7691         }
7692         // *w = 0; /* terminate class name */
7693  end:
7694         if (!info->name || !*info->name)
7695                 return 0;
7696         if (endptr)
7697                 *endptr = p;
7698         /* add other consistency checks */
7699         return 1;
7700 }
7701
7702
7703 /**
7704  * mono_identifier_unescape_type_name_chars:
7705  * @identifier: the display name of a mono type
7706  *
7707  * Returns:
7708  *  The name in internal form, that is without escaping backslashes.
7709  *
7710  *  The string is modified in place!
7711  */
7712 char*
7713 mono_identifier_unescape_type_name_chars(char* identifier)
7714 {
7715         char *w, *r;
7716         if (!identifier)
7717                 return NULL;
7718         for (w = r = identifier; *r != 0; r++)
7719         {
7720                 char c = *r;
7721                 if (c == '\\') {
7722                         r++;
7723                         if (*r == 0)
7724                                 break;
7725                         c = *r;
7726                 }
7727                 *w = c;
7728                 w++;
7729         }
7730         if (w != r)
7731                 *w = 0;
7732         return identifier;
7733 }
7734
7735 void
7736 mono_identifier_unescape_info (MonoTypeNameParse* info);
7737
7738 static void
7739 unescape_each_type_argument(void* data, void* user_data)
7740 {
7741         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7742         mono_identifier_unescape_info (info);
7743 }
7744
7745 static void
7746 unescape_each_nested_name (void* data, void* user_data)
7747 {
7748         char* nested_name = (char*) data;
7749         mono_identifier_unescape_type_name_chars(nested_name);
7750 }
7751
7752 /**
7753  * mono_identifier_unescape_info:
7754  *
7755  * @info: a parsed display form of an (optionally assembly qualified) full type name.
7756  *
7757  * Returns: nothing.
7758  *
7759  * Destructively updates the info by unescaping the identifiers that
7760  * comprise the type namespace, name, nested types (if any) and
7761  * generic type arguments (if any).
7762  *
7763  * The resulting info has the names in internal form.
7764  *
7765  */
7766 void
7767 mono_identifier_unescape_info (MonoTypeNameParse *info)
7768 {
7769         if (!info)
7770                 return;
7771         mono_identifier_unescape_type_name_chars(info->name_space);
7772         mono_identifier_unescape_type_name_chars(info->name);
7773         // but don't escape info->assembly
7774         if (info->type_arguments)
7775                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7776         if (info->nested)
7777                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7778 }
7779
7780 int
7781 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7782 {
7783         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7784         if (ok) {
7785                 mono_identifier_unescape_info (info);
7786         }
7787         return ok;
7788 }
7789
7790 static MonoType*
7791 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7792 {
7793         gboolean type_resolve = FALSE;
7794         MonoType *type;
7795         MonoImage *rootimage = image;
7796
7797         if (info->assembly.name) {
7798                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7799                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7800                         /* 
7801                          * This could happen in the AOT compiler case when the search hook is not
7802                          * installed.
7803                          */
7804                         assembly = image->assembly;
7805                 if (!assembly) {
7806                         /* then we must load the assembly ourselve - see #60439 */
7807                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7808                         if (!assembly)
7809                                 return NULL;
7810                 }
7811                 image = assembly->image;
7812         } else if (!image) {
7813                 image = mono_defaults.corlib;
7814         }
7815
7816         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7817         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7818                 image = mono_defaults.corlib;
7819                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7820         }
7821
7822         return type;
7823 }
7824
7825 static MonoType*
7826 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7827 {
7828         MonoClass *klass;
7829         GList *mod;
7830         int modval;
7831         gboolean bounded = FALSE;
7832         
7833         if (!image)
7834                 image = mono_defaults.corlib;
7835
7836         if (!rootimage)
7837                 rootimage = mono_defaults.corlib;
7838
7839         if (ignorecase) {
7840                 MonoError error;
7841                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7842                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7843         } else {
7844                 klass = mono_class_from_name (image, info->name_space, info->name);
7845         }
7846         if (!klass)
7847                 return NULL;
7848         for (mod = info->nested; mod; mod = mod->next) {
7849                 gpointer iter = NULL;
7850                 MonoClass *parent;
7851
7852                 parent = klass;
7853                 mono_class_init (parent);
7854
7855                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7856                         char *lastp;
7857                         char *nested_name, *nested_nspace;
7858                         gboolean match = TRUE;
7859
7860                         lastp = strrchr ((const char *)mod->data, '.');
7861                         if (lastp) {
7862                                 /* Nested classes can have namespaces */
7863                                 int nspace_len;
7864
7865                                 nested_name = g_strdup (lastp + 1);
7866                                 nspace_len = lastp - (char*)mod->data;
7867                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
7868                                 memcpy (nested_nspace, mod->data, nspace_len);
7869                                 nested_nspace [nspace_len] = '\0';
7870
7871                         } else {
7872                                 nested_name = (char *)mod->data;
7873                                 nested_nspace = NULL;
7874                         }
7875
7876                         if (nested_nspace) {
7877                                 if (ignorecase) {
7878                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7879                                                 match = FALSE;
7880                                 } else {
7881                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7882                                                 match = FALSE;
7883                                 }
7884                         }
7885                         if (match) {
7886                                 if (ignorecase) {
7887                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7888                                                 match = FALSE;
7889                                 } else {
7890                                         if (strcmp (klass->name, nested_name) != 0)
7891                                                 match = FALSE;
7892                                 }
7893                         }
7894                         if (lastp) {
7895                                 g_free (nested_name);
7896                                 g_free (nested_nspace);
7897                         }
7898                         if (match)
7899                                 break;
7900                 }
7901
7902                 if (!klass)
7903                         break;
7904         }
7905         if (!klass)
7906                 return NULL;
7907
7908         if (info->type_arguments) {
7909                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7910                 MonoReflectionType *the_type;
7911                 MonoType *instance;
7912                 int i;
7913
7914                 for (i = 0; i < info->type_arguments->len; i++) {
7915                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
7916
7917                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7918                         if (!type_args [i]) {
7919                                 g_free (type_args);
7920                                 return NULL;
7921                         }
7922                 }
7923
7924                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7925
7926                 instance = mono_reflection_bind_generic_parameters (
7927                         the_type, info->type_arguments->len, type_args);
7928
7929                 g_free (type_args);
7930                 if (!instance)
7931                         return NULL;
7932
7933                 klass = mono_class_from_mono_type (instance);
7934         }
7935
7936         for (mod = info->modifiers; mod; mod = mod->next) {
7937                 modval = GPOINTER_TO_UINT (mod->data);
7938                 if (!modval) { /* byref: must be last modifier */
7939                         return &klass->this_arg;
7940                 } else if (modval == -1) {
7941                         klass = mono_ptr_class_get (&klass->byval_arg);
7942                 } else if (modval == -2) {
7943                         bounded = TRUE;
7944                 } else { /* array rank */
7945                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7946                 }
7947         }
7948
7949         return &klass->byval_arg;
7950 }
7951
7952 /*
7953  * mono_reflection_get_type:
7954  * @image: a metadata context
7955  * @info: type description structure
7956  * @ignorecase: flag for case-insensitive string compares
7957  * @type_resolve: whenever type resolve was already tried
7958  *
7959  * Build a MonoType from the type description in @info.
7960  * 
7961  */
7962
7963 MonoType*
7964 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7965         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7966 }
7967
7968 static MonoType*
7969 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7970 {
7971         MonoReflectionAssemblyBuilder *abuilder;
7972         MonoType *type;
7973         int i;
7974
7975         g_assert (assembly_is_dynamic (assembly));
7976         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7977
7978         /* Enumerate all modules */
7979
7980         type = NULL;
7981         if (abuilder->modules) {
7982                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7983                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7984                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7985                         if (type)
7986                                 break;
7987                 }
7988         }
7989
7990         if (!type && abuilder->loaded_modules) {
7991                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7992                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7993                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7994                         if (type)
7995                                 break;
7996                 }
7997         }
7998
7999         return type;
8000 }
8001         
8002 MonoType*
8003 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8004 {
8005         MonoType *type;
8006         MonoReflectionAssembly *assembly;
8007         GString *fullName;
8008         GList *mod;
8009
8010         if (image && image_is_dynamic (image))
8011                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
8012         else
8013                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
8014         if (type)
8015                 return type;
8016         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8017                 return NULL;
8018
8019         if (type_resolve) {
8020                 if (*type_resolve) 
8021                         return NULL;
8022                 else
8023                         *type_resolve = TRUE;
8024         }
8025         
8026         /* Reconstruct the type name */
8027         fullName = g_string_new ("");
8028         if (info->name_space && (info->name_space [0] != '\0'))
8029                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8030         else
8031                 g_string_printf (fullName, "%s", info->name);
8032         for (mod = info->nested; mod; mod = mod->next)
8033                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8034
8035         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
8036         if (assembly) {
8037                 if (assembly_is_dynamic (assembly->assembly))
8038                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
8039                 else
8040                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8041                                                                                                           info, ignorecase);
8042         }
8043         g_string_free (fullName, TRUE);
8044         return type;
8045 }
8046
8047 void
8048 mono_reflection_free_type_info (MonoTypeNameParse *info)
8049 {
8050         g_list_free (info->modifiers);
8051         g_list_free (info->nested);
8052
8053         if (info->type_arguments) {
8054                 int i;
8055
8056                 for (i = 0; i < info->type_arguments->len; i++) {
8057                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8058
8059                         mono_reflection_free_type_info (subinfo);
8060                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8061                         g_free (subinfo);
8062                 }
8063
8064                 g_ptr_array_free (info->type_arguments, TRUE);
8065         }
8066 }
8067
8068 /*
8069  * mono_reflection_type_from_name:
8070  * @name: type name.
8071  * @image: a metadata context (can be NULL).
8072  *
8073  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8074  * it defaults to get the type from @image or, if @image is NULL or loading
8075  * from it fails, uses corlib.
8076  * 
8077  */
8078 MonoType*
8079 mono_reflection_type_from_name (char *name, MonoImage *image)
8080 {
8081         MonoType *type = NULL;
8082         MonoTypeNameParse info;
8083         char *tmp;
8084
8085         /* Make a copy since parse_type modifies its argument */
8086         tmp = g_strdup (name);
8087         
8088         /*g_print ("requested type %s\n", str);*/
8089         if (mono_reflection_parse_type (tmp, &info)) {
8090                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8091         }
8092
8093         g_free (tmp);
8094         mono_reflection_free_type_info (&info);
8095         return type;
8096 }
8097
8098 /*
8099  * mono_reflection_get_token:
8100  *
8101  *   Return the metadata token of OBJ which should be an object
8102  * representing a metadata element.
8103  */
8104 guint32
8105 mono_reflection_get_token (MonoObject *obj)
8106 {
8107         MonoClass *klass;
8108         guint32 token = 0;
8109
8110         klass = obj->vtable->klass;
8111
8112         if (strcmp (klass->name, "MethodBuilder") == 0) {
8113                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8114
8115                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8116         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8117                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8118
8119                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8120         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8121                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8122
8123                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8124         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8125                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8126                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8127         } else if (strcmp (klass->name, "MonoType") == 0) {
8128                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8129                 MonoClass *mc = mono_class_from_mono_type (type);
8130                 if (!mono_class_init (mc))
8131                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8132
8133                 token = mc->type_token;
8134         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8135                    strcmp (klass->name, "MonoMethod") == 0 ||
8136                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8137                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8138                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8139                 if (m->method->is_inflated) {
8140                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8141                         return inflated->declaring->token;
8142                 } else {
8143                         token = m->method->token;
8144                 }
8145         } else if (strcmp (klass->name, "MonoField") == 0) {
8146                 MonoReflectionField *f = (MonoReflectionField*)obj;
8147
8148                 if (is_field_on_inst (f->field)) {
8149                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8150
8151                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8152                                 int field_index = f->field - dgclass->fields;
8153                                 MonoObject *obj;
8154
8155                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8156                                 obj = dgclass->field_objects [field_index];
8157                                 return mono_reflection_get_token (obj);
8158                         }
8159                 }
8160                 token = mono_class_get_field_token (f->field);
8161         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8162                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8163
8164                 token = mono_class_get_property_token (p->property);
8165         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8166                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8167
8168                 token = mono_class_get_event_token (p->event);
8169         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8170                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8171                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8172                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8173
8174                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8175         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8176                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8177
8178                 token = m->token;
8179         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8180                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8181         } else {
8182                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8183                 MonoException *ex = mono_get_exception_not_implemented (msg);
8184                 g_free (msg);
8185                 mono_raise_exception (ex);
8186         }
8187
8188         return token;
8189 }
8190
8191 static MonoClass*
8192 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8193 {
8194         char *n;
8195         MonoType *t;
8196         int slen = mono_metadata_decode_value (p, &p);
8197
8198         mono_error_init (error);
8199
8200         n = (char *)g_memdup (p, slen + 1);
8201         n [slen] = 0;
8202         t = mono_reflection_type_from_name (n, image);
8203         if (!t) {
8204                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8205                 /* We don't free n, it's consumed by mono_error */
8206                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8207                 return NULL;
8208         }
8209         g_free (n);
8210         p += slen;
8211         *end = p;
8212         return mono_class_from_mono_type (t);
8213 }
8214
8215 static void*
8216 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8217 {
8218         int slen, type = t->type;
8219         MonoClass *tklass = t->data.klass;
8220
8221         mono_error_init (error);
8222
8223 handle_enum:
8224         switch (type) {
8225         case MONO_TYPE_U1:
8226         case MONO_TYPE_I1:
8227         case MONO_TYPE_BOOLEAN: {
8228                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8229                 *bval = *p;
8230                 *end = p + 1;
8231                 return bval;
8232         }
8233         case MONO_TYPE_CHAR:
8234         case MONO_TYPE_U2:
8235         case MONO_TYPE_I2: {
8236                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8237                 *val = read16 (p);
8238                 *end = p + 2;
8239                 return val;
8240         }
8241 #if SIZEOF_VOID_P == 4
8242         case MONO_TYPE_U:
8243         case MONO_TYPE_I:
8244 #endif
8245         case MONO_TYPE_R4:
8246         case MONO_TYPE_U4:
8247         case MONO_TYPE_I4: {
8248                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8249                 *val = read32 (p);
8250                 *end = p + 4;
8251                 return val;
8252         }
8253 #if SIZEOF_VOID_P == 8
8254         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8255         case MONO_TYPE_I:
8256 #endif
8257         case MONO_TYPE_U8:
8258         case MONO_TYPE_I8: {
8259                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8260                 *val = read64 (p);
8261                 *end = p + 8;
8262                 return val;
8263         }
8264         case MONO_TYPE_R8: {
8265                 double *val = (double *)g_malloc (sizeof (double));
8266                 readr8 (p, val);
8267                 *end = p + 8;
8268                 return val;
8269         }
8270         case MONO_TYPE_VALUETYPE:
8271                 if (t->data.klass->enumtype) {
8272                         type = mono_class_enum_basetype (t->data.klass)->type;
8273                         goto handle_enum;
8274                 } else {
8275                         MonoClass *k =  t->data.klass;
8276                         
8277                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8278                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8279                                 *val = read64 (p);
8280                                 *end = p + 8;
8281                                 return val;
8282                         }
8283                 }
8284                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8285                 break;
8286                 
8287         case MONO_TYPE_STRING:
8288                 if (*p == (char)0xFF) {
8289                         *end = p + 1;
8290                         return NULL;
8291                 }
8292                 slen = mono_metadata_decode_value (p, &p);
8293                 *end = p + slen;
8294                 return mono_string_new_len (mono_domain_get (), p, slen);
8295         case MONO_TYPE_CLASS: {
8296                 char *n;
8297                 MonoType *t;
8298                 if (*p == (char)0xFF) {
8299                         *end = p + 1;
8300                         return NULL;
8301                 }
8302 handle_type:
8303                 slen = mono_metadata_decode_value (p, &p);
8304                 n = (char *)g_memdup (p, slen + 1);
8305                 n [slen] = 0;
8306                 t = mono_reflection_type_from_name (n, image);
8307                 if (!t) {
8308                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8309                         /* We don't free n, it's consumed by mono_error */
8310                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8311                         return NULL;
8312                 }
8313                 g_free (n);
8314                 *end = p + slen;
8315                 return mono_type_get_object (mono_domain_get (), t);
8316         }
8317         case MONO_TYPE_OBJECT: {
8318                 char subt = *p++;
8319                 MonoObject *obj;
8320                 MonoClass *subc = NULL;
8321                 void *val;
8322
8323                 if (subt == 0x50) {
8324                         goto handle_type;
8325                 } else if (subt == 0x0E) {
8326                         type = MONO_TYPE_STRING;
8327                         goto handle_enum;
8328                 } else if (subt == 0x1D) {
8329                         MonoType simple_type = {{0}};
8330                         int etype = *p;
8331                         p ++;
8332
8333                         type = MONO_TYPE_SZARRAY;
8334                         if (etype == 0x50) {
8335                                 tklass = mono_defaults.systemtype_class;
8336                         } else if (etype == 0x55) {
8337                                 tklass = load_cattr_enum_type (image, p, &p, error);
8338                                 if (!mono_error_ok (error))
8339                                         return NULL;
8340                         } else {
8341                                 if (etype == 0x51)
8342                                         /* See Partition II, Appendix B3 */
8343                                         etype = MONO_TYPE_OBJECT;
8344                                 simple_type.type = (MonoTypeEnum)etype;
8345                                 tklass = mono_class_from_mono_type (&simple_type);
8346                         }
8347                         goto handle_enum;
8348                 } else if (subt == 0x55) {
8349                         char *n;
8350                         MonoType *t;
8351                         slen = mono_metadata_decode_value (p, &p);
8352                         n = (char *)g_memdup (p, slen + 1);
8353                         n [slen] = 0;
8354                         t = mono_reflection_type_from_name (n, image);
8355                         if (!t) {
8356                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8357                                 /* We don't free n, it's consumed by mono_error */
8358                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8359                                 return NULL;
8360                         }
8361                         g_free (n);
8362                         p += slen;
8363                         subc = mono_class_from_mono_type (t);
8364                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8365                         MonoType simple_type = {{0}};
8366                         simple_type.type = (MonoTypeEnum)subt;
8367                         subc = mono_class_from_mono_type (&simple_type);
8368                 } else {
8369                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8370                 }
8371                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8372                 obj = NULL;
8373                 if (mono_error_ok (error)) {
8374                         obj = mono_object_new (mono_domain_get (), subc);
8375                         g_assert (!subc->has_references);
8376                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8377                 }
8378
8379                 g_free (val);
8380                 return obj;
8381         }
8382         case MONO_TYPE_SZARRAY: {
8383                 MonoArray *arr;
8384                 guint32 i, alen, basetype;
8385                 alen = read32 (p);
8386                 p += 4;
8387                 if (alen == 0xffffffff) {
8388                         *end = p;
8389                         return NULL;
8390                 }
8391                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8392                 basetype = tklass->byval_arg.type;
8393                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8394                         basetype = mono_class_enum_basetype (tklass)->type;
8395                 switch (basetype)
8396                 {
8397                         case MONO_TYPE_U1:
8398                         case MONO_TYPE_I1:
8399                         case MONO_TYPE_BOOLEAN:
8400                                 for (i = 0; i < alen; i++) {
8401                                         MonoBoolean val = *p++;
8402                                         mono_array_set (arr, MonoBoolean, i, val);
8403                                 }
8404                                 break;
8405                         case MONO_TYPE_CHAR:
8406                         case MONO_TYPE_U2:
8407                         case MONO_TYPE_I2:
8408                                 for (i = 0; i < alen; i++) {
8409                                         guint16 val = read16 (p);
8410                                         mono_array_set (arr, guint16, i, val);
8411                                         p += 2;
8412                                 }
8413                                 break;
8414                         case MONO_TYPE_R4:
8415                         case MONO_TYPE_U4:
8416                         case MONO_TYPE_I4:
8417                                 for (i = 0; i < alen; i++) {
8418                                         guint32 val = read32 (p);
8419                                         mono_array_set (arr, guint32, i, val);
8420                                         p += 4;
8421                                 }
8422                                 break;
8423                         case MONO_TYPE_R8:
8424                                 for (i = 0; i < alen; i++) {
8425                                         double val;
8426                                         readr8 (p, &val);
8427                                         mono_array_set (arr, double, i, val);
8428                                         p += 8;
8429                                 }
8430                                 break;
8431                         case MONO_TYPE_U8:
8432                         case MONO_TYPE_I8:
8433                                 for (i = 0; i < alen; i++) {
8434                                         guint64 val = read64 (p);
8435                                         mono_array_set (arr, guint64, i, val);
8436                                         p += 8;
8437                                 }
8438                                 break;
8439                         case MONO_TYPE_CLASS:
8440                         case MONO_TYPE_OBJECT:
8441                         case MONO_TYPE_STRING:
8442                         case MONO_TYPE_SZARRAY:
8443                                 for (i = 0; i < alen; i++) {
8444                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8445                                         if (!mono_error_ok (error))
8446                                                 return NULL;
8447                                         mono_array_setref (arr, i, item);
8448                                 }
8449                                 break;
8450                         default:
8451                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8452                 }
8453                 *end=p;
8454                 return arr;
8455         }
8456         default:
8457                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8458         }
8459         return NULL;
8460 }
8461
8462 static MonoObject*
8463 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8464 {
8465         static MonoClass *klass;
8466         static MonoMethod *ctor;
8467         MonoObject *retval;
8468         void *params [2], *unboxed;
8469
8470         if (!klass)
8471                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8472         if (!ctor)
8473                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8474         
8475         params [0] = mono_type_get_object (mono_domain_get (), t);
8476         params [1] = val;
8477         retval = mono_object_new (mono_domain_get (), klass);
8478         unboxed = mono_object_unbox (retval);
8479         mono_runtime_invoke (ctor, unboxed, params, NULL);
8480
8481         return retval;
8482 }
8483
8484 static MonoObject*
8485 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8486 {
8487         static MonoClass *klass;
8488         static MonoMethod *ctor;
8489         MonoObject *retval;
8490         void *unboxed, *params [2];
8491
8492         if (!klass)
8493                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8494         if (!ctor)
8495                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8496
8497         params [0] = minfo;
8498         params [1] = typedarg;
8499         retval = mono_object_new (mono_domain_get (), klass);
8500         unboxed = mono_object_unbox (retval);
8501         mono_runtime_invoke (ctor, unboxed, params, NULL);
8502
8503         return retval;
8504 }
8505
8506 static gboolean
8507 type_is_reference (MonoType *type)
8508 {
8509         switch (type->type) {
8510         case MONO_TYPE_BOOLEAN:
8511         case MONO_TYPE_CHAR:
8512         case MONO_TYPE_U:
8513         case MONO_TYPE_I:
8514         case MONO_TYPE_U1:
8515         case MONO_TYPE_I1:
8516         case MONO_TYPE_U2:
8517         case MONO_TYPE_I2:
8518         case MONO_TYPE_U4:
8519         case MONO_TYPE_I4:
8520         case MONO_TYPE_U8:
8521         case MONO_TYPE_I8:
8522         case MONO_TYPE_R8:
8523         case MONO_TYPE_R4:
8524         case MONO_TYPE_VALUETYPE:
8525                 return FALSE;
8526         default:
8527                 return TRUE;
8528         }
8529 }
8530
8531 static void
8532 free_param_data (MonoMethodSignature *sig, void **params) {
8533         int i;
8534         for (i = 0; i < sig->param_count; ++i) {
8535                 if (!type_is_reference (sig->params [i]))
8536                         g_free (params [i]);
8537         }
8538 }
8539
8540 /*
8541  * Find the field index in the metadata FieldDef table.
8542  */
8543 static guint32
8544 find_field_index (MonoClass *klass, MonoClassField *field) {
8545         int i;
8546
8547         for (i = 0; i < klass->field.count; ++i) {
8548                 if (field == &klass->fields [i])
8549                         return klass->field.first + 1 + i;
8550         }
8551         return 0;
8552 }
8553
8554 /*
8555  * Find the property index in the metadata Property table.
8556  */
8557 static guint32
8558 find_property_index (MonoClass *klass, MonoProperty *property) {
8559         int i;
8560
8561         for (i = 0; i < klass->ext->property.count; ++i) {
8562                 if (property == &klass->ext->properties [i])
8563                         return klass->ext->property.first + 1 + i;
8564         }
8565         return 0;
8566 }
8567
8568 /*
8569  * Find the event index in the metadata Event table.
8570  */
8571 static guint32
8572 find_event_index (MonoClass *klass, MonoEvent *event) {
8573         int i;
8574
8575         for (i = 0; i < klass->ext->event.count; ++i) {
8576                 if (event == &klass->ext->events [i])
8577                         return klass->ext->event.first + 1 + i;
8578         }
8579         return 0;
8580 }
8581
8582 static MonoObject*
8583 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8584 {
8585         const char *p = (const char*)data;
8586         const char *named;
8587         guint32 i, j, num_named;
8588         MonoObject *attr;
8589         void *params_buf [32];
8590         void **params = NULL;
8591         MonoMethodSignature *sig;
8592         MonoObject *exc = NULL;
8593
8594         mono_error_init (error);
8595
8596         mono_class_init (method->klass);
8597
8598         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8599                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8600                 return NULL;
8601         }
8602
8603         if (len == 0) {
8604                 attr = mono_object_new (mono_domain_get (), method->klass);
8605                 mono_runtime_invoke (method, attr, NULL, NULL);
8606                 return attr;
8607         }
8608
8609         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8610                 return NULL;
8611
8612         /*g_print ("got attr %s\n", method->klass->name);*/
8613
8614         sig = mono_method_signature (method);
8615         if (sig->param_count < 32) {
8616                 params = params_buf;
8617                 memset (params, 0, sizeof (void*) * sig->param_count);
8618         } else {
8619                 /* Allocate using GC so it gets GC tracking */
8620                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8621         }
8622
8623         /* skip prolog */
8624         p += 2;
8625         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8626                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8627                 if (!mono_error_ok (error))
8628                         goto fail;
8629         }
8630
8631         named = p;
8632         attr = mono_object_new (mono_domain_get (), method->klass);
8633
8634         mono_runtime_invoke (method, attr, params, &exc);
8635         if (exc)
8636                 goto fail;
8637         num_named = read16 (named);
8638         named += 2;
8639         for (j = 0; j < num_named; j++) {
8640                 gint name_len;
8641                 char *name, named_type, data_type;
8642                 named_type = *named++;
8643                 data_type = *named++; /* type of data */
8644                 if (data_type == MONO_TYPE_SZARRAY)
8645                         data_type = *named++;
8646                 if (data_type == MONO_TYPE_ENUM) {
8647                         gint type_len;
8648                         char *type_name;
8649                         type_len = mono_metadata_decode_blob_size (named, &named);
8650                         type_name = (char *)g_malloc (type_len + 1);
8651                         memcpy (type_name, named, type_len);
8652                         type_name [type_len] = 0;
8653                         named += type_len;
8654                         /* FIXME: lookup the type and check type consistency */
8655                         g_free (type_name);
8656                 }
8657                 name_len = mono_metadata_decode_blob_size (named, &named);
8658                 name = (char *)g_malloc (name_len + 1);
8659                 memcpy (name, named, name_len);
8660                 name [name_len] = 0;
8661                 named += name_len;
8662                 if (named_type == 0x53) {
8663                         MonoClassField *field;
8664                         void *val;
8665
8666                         /* how this fail is a blackbox */
8667                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8668                         if (!field) {
8669                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8670                                 g_free (name);
8671                                 goto fail;
8672                         }
8673
8674                         val = load_cattr_value (image, field->type, named, &named, error);
8675                         if (!mono_error_ok (error)) {
8676                                 g_free (name);
8677                                 if (!type_is_reference (field->type))
8678                                         g_free (val);
8679                                 goto fail;
8680                         }
8681
8682                         mono_field_set_value (attr, field, val);
8683                         if (!type_is_reference (field->type))
8684                                 g_free (val);
8685                 } else if (named_type == 0x54) {
8686                         MonoProperty *prop;
8687                         void *pparams [1];
8688                         MonoType *prop_type;
8689
8690                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8691
8692                         if (!prop) {
8693                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8694                                 g_free (name);
8695                                 goto fail;
8696                         }
8697
8698                         if (!prop->set) {
8699                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8700                                 g_free (name);
8701                                 goto fail;
8702                         }
8703
8704                         /* can we have more that 1 arg in a custom attr named property? */
8705                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8706                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8707
8708                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8709                         if (!mono_error_ok (error)) {
8710                                 g_free (name);
8711                                 if (!type_is_reference (prop_type))
8712                                         g_free (pparams [0]);
8713                                 goto fail;
8714                         }
8715
8716
8717                         mono_property_set_value (prop, attr, pparams, NULL);
8718                         if (!type_is_reference (prop_type))
8719                                 g_free (pparams [0]);
8720                 }
8721                 g_free (name);
8722         }
8723
8724         free_param_data (method->signature, params);
8725         if (params != params_buf)
8726                 mono_gc_free_fixed (params);
8727
8728         return attr;
8729
8730 fail:
8731         free_param_data (method->signature, params);
8732         if (params != params_buf)
8733                 mono_gc_free_fixed (params);
8734         if (exc)
8735                 mono_raise_exception ((MonoException*)exc);
8736         return NULL;
8737 }
8738         
8739 /*
8740  * mono_reflection_create_custom_attr_data_args:
8741  *
8742  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8743  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8744  * NAMED_ARG_INFO will contain information about the named arguments.
8745  */
8746 void
8747 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)
8748 {
8749         MonoArray *typedargs, *namedargs;
8750         MonoClass *attrklass;
8751         MonoDomain *domain;
8752         const char *p = (const char*)data;
8753         const char *named;
8754         guint32 i, j, num_named;
8755         CattrNamedArg *arginfo = NULL;
8756
8757         *typed_args = NULL;
8758         *named_args = NULL;
8759         *named_arg_info = NULL;
8760
8761         mono_error_init (error);
8762
8763         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8764                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8765                 return;
8766         }
8767
8768         mono_class_init (method->klass);
8769         
8770         domain = mono_domain_get ();
8771
8772         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8773                 return;
8774
8775         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8776         
8777         /* skip prolog */
8778         p += 2;
8779         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8780                 MonoObject *obj;
8781                 void *val;
8782
8783                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8784                 if (!mono_error_ok (error)) {
8785                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8786                                 g_free (val);
8787                         return;
8788                 }
8789
8790                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
8791                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
8792                 mono_array_setref (typedargs, i, obj);
8793
8794                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8795                         g_free (val);
8796         }
8797
8798         named = p;
8799         num_named = read16 (named);
8800         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8801         named += 2;
8802         attrklass = method->klass;
8803
8804         arginfo = g_new0 (CattrNamedArg, num_named);
8805         *named_arg_info = arginfo;
8806
8807         for (j = 0; j < num_named; j++) {
8808                 gint name_len;
8809                 char *name, named_type, data_type;
8810                 named_type = *named++;
8811                 data_type = *named++; /* type of data */
8812                 if (data_type == MONO_TYPE_SZARRAY)
8813                         data_type = *named++;
8814                 if (data_type == MONO_TYPE_ENUM) {
8815                         gint type_len;
8816                         char *type_name;
8817                         type_len = mono_metadata_decode_blob_size (named, &named);
8818                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8819                                 goto fail;
8820
8821                         type_name = (char *)g_malloc (type_len + 1);
8822                         memcpy (type_name, named, type_len);
8823                         type_name [type_len] = 0;
8824                         named += type_len;
8825                         /* FIXME: lookup the type and check type consistency */
8826                         g_free (type_name);
8827                 }
8828                 name_len = mono_metadata_decode_blob_size (named, &named);
8829                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8830                         goto fail;
8831                 name = (char *)g_malloc (name_len + 1);
8832                 memcpy (name, named, name_len);
8833                 name [name_len] = 0;
8834                 named += name_len;
8835                 if (named_type == 0x53) {
8836                         MonoObject *obj;
8837                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8838                         void *val;
8839
8840                         if (!field) {
8841                                 g_free (name);
8842                                 goto fail;
8843                         }
8844
8845                         arginfo [j].type = field->type;
8846                         arginfo [j].field = field;
8847
8848                         val = load_cattr_value (image, field->type, named, &named, error);
8849                         if (!mono_error_ok (error)) {
8850                                 if (!type_is_reference (field->type))
8851                                         g_free (val);
8852                                 g_free (name);
8853                                 return;
8854                         }
8855
8856                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
8857                         mono_array_setref (namedargs, j, obj);
8858                         if (!type_is_reference (field->type))
8859                                 g_free (val);
8860                 } else if (named_type == 0x54) {
8861                         MonoObject *obj;
8862                         MonoType *prop_type;
8863                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8864                         void *val;
8865
8866                         if (!prop || !prop->set) {
8867                                 g_free (name);
8868                                 goto fail;
8869                         }
8870
8871                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8872                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8873
8874                         arginfo [j].type = prop_type;
8875                         arginfo [j].prop = prop;
8876
8877                         val = load_cattr_value (image, prop_type, named, &named, error);
8878                         if (!mono_error_ok (error)) {
8879                                 if (!type_is_reference (prop_type))
8880                                         g_free (val);
8881                                 g_free (name);
8882                                 return;
8883                         }
8884
8885                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
8886                         mono_array_setref (namedargs, j, obj);
8887                         if (!type_is_reference (prop_type))
8888                                 g_free (val);
8889                 }
8890                 g_free (name);
8891         }
8892
8893         *typed_args = typedargs;
8894         *named_args = namedargs;
8895         return;
8896 fail:
8897         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8898         g_free (arginfo);
8899         *named_arg_info = NULL;
8900 }
8901
8902 void
8903 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8904 {
8905         MonoDomain *domain;
8906         MonoArray *typedargs, *namedargs;
8907         MonoImage *image;
8908         MonoMethod *method;
8909         CattrNamedArg *arginfo = NULL;
8910         MonoError error;
8911         int i;
8912
8913         *ctor_args = NULL;
8914         *named_args = NULL;
8915
8916         if (len == 0)
8917                 return;
8918
8919         image = assembly->assembly->image;
8920         method = ref_method->method;
8921         domain = mono_object_domain (ref_method);
8922
8923         if (!mono_class_init (method->klass))
8924                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8925
8926         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
8927         if (!mono_error_ok (&error))
8928                 mono_error_raise_exception (&error);
8929         if (mono_loader_get_last_error ())
8930                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8931
8932         if (!typedargs || !namedargs) {
8933                 g_free (arginfo);
8934                 return;
8935         }
8936
8937         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8938                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8939                 MonoObject *typedarg;
8940
8941                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8942                 mono_array_setref (typedargs, i, typedarg);
8943         }
8944
8945         for (i = 0; i < mono_array_length (namedargs); ++i) {
8946                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8947                 MonoObject *typedarg, *namedarg, *minfo;
8948
8949                 if (arginfo [i].prop)
8950                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8951                 else
8952                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8953
8954                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8955                 namedarg = create_cattr_named_arg (minfo, typedarg);
8956
8957                 mono_array_setref (namedargs, i, namedarg);
8958         }
8959
8960         *ctor_args = typedargs;
8961         *named_args = namedargs;
8962         g_free (arginfo);
8963 }
8964
8965 static MonoObject*
8966 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8967 {
8968         static MonoMethod *ctor;
8969         MonoDomain *domain;
8970         MonoObject *attr;
8971         void *params [4];
8972
8973         g_assert (image->assembly);
8974
8975         if (!ctor)
8976                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8977
8978         domain = mono_domain_get ();
8979         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8980         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8981         params [1] = mono_assembly_get_object (domain, image->assembly);
8982         params [2] = (gpointer)&cattr->data;
8983         params [3] = &cattr->data_size;
8984         mono_runtime_invoke (ctor, attr, params, NULL);
8985         return attr;
8986 }
8987
8988 static MonoArray*
8989 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8990 {
8991         MonoArray *result;
8992         MonoObject *attr;
8993         int i, n;
8994
8995         mono_error_init (error);
8996
8997         n = 0;
8998         for (i = 0; i < cinfo->num_attrs; ++i) {
8999                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9000                         n ++;
9001         }
9002
9003         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9004         n = 0;
9005         for (i = 0; i < cinfo->num_attrs; ++i) {
9006                 if (!cinfo->attrs [i].ctor)
9007                         /* The cattr type is not finished yet */
9008                         /* We should include the type name but cinfo doesn't contain it */
9009                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9010                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9011                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9012                         if (!mono_error_ok (error))
9013                                 return result;
9014                         mono_array_setref (result, n, attr);
9015                         n ++;
9016                 }
9017         }
9018         return result;
9019 }
9020
9021 MonoArray*
9022 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9023 {
9024         MonoError error;
9025         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9026         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9027
9028         return result;
9029 }
9030
9031 static MonoArray*
9032 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
9033 {
9034         MonoArray *result;
9035         MonoObject *attr;
9036         int i;
9037         
9038         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9039         for (i = 0; i < cinfo->num_attrs; ++i) {
9040                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
9041                 mono_array_setref (result, i, attr);
9042         }
9043         return result;
9044 }
9045
9046 /**
9047  * mono_custom_attrs_from_index:
9048  *
9049  * Returns: NULL if no attributes are found or if a loading error occurs.
9050  */
9051 MonoCustomAttrInfo*
9052 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9053 {
9054         guint32 mtoken, i, len;
9055         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9056         MonoTableInfo *ca;
9057         MonoCustomAttrInfo *ainfo;
9058         GList *tmp, *list = NULL;
9059         const char *data;
9060         MonoCustomAttrEntry* attr;
9061
9062         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9063
9064         i = mono_metadata_custom_attrs_from_index (image, idx);
9065         if (!i)
9066                 return NULL;
9067         i --;
9068         while (i < ca->rows) {
9069                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9070                         break;
9071                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9072                 ++i;
9073         }
9074         len = g_list_length (list);
9075         if (!len)
9076                 return NULL;
9077         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9078         ainfo->num_attrs = len;
9079         ainfo->image = image;
9080         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9081                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9082                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9083                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9084                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9085                         mtoken |= MONO_TOKEN_METHOD_DEF;
9086                         break;
9087                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9088                         mtoken |= MONO_TOKEN_MEMBER_REF;
9089                         break;
9090                 default:
9091                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9092                         break;
9093                 }
9094                 attr = &ainfo->attrs [i - 1];
9095                 attr->ctor = mono_get_method (image, mtoken, NULL);
9096                 if (!attr->ctor) {
9097                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
9098                         g_list_free (list);
9099                         g_free (ainfo);
9100                         return NULL;
9101                 }
9102
9103                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9104                         /*FIXME raising an exception here doesn't make any sense*/
9105                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9106                         g_list_free (list);
9107                         g_free (ainfo);
9108                         return NULL;
9109                 }
9110                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9111                 attr->data_size = mono_metadata_decode_value (data, &data);
9112                 attr->data = (guchar*)data;
9113         }
9114         g_list_free (list);
9115
9116         return ainfo;
9117 }
9118
9119 MonoCustomAttrInfo*
9120 mono_custom_attrs_from_method (MonoMethod *method)
9121 {
9122         guint32 idx;
9123
9124         /*
9125          * An instantiated method has the same cattrs as the generic method definition.
9126          *
9127          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9128          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9129          */
9130         if (method->is_inflated)
9131                 method = ((MonoMethodInflated *) method)->declaring;
9132         
9133         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9134                 return lookup_custom_attr (method->klass->image, method);
9135
9136         if (!method->token)
9137                 /* Synthetic methods */
9138                 return NULL;
9139
9140         idx = mono_method_get_index (method);
9141         idx <<= MONO_CUSTOM_ATTR_BITS;
9142         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9143         return mono_custom_attrs_from_index (method->klass->image, idx);
9144 }
9145
9146 MonoCustomAttrInfo*
9147 mono_custom_attrs_from_class (MonoClass *klass)
9148 {
9149         guint32 idx;
9150
9151         if (klass->generic_class)
9152                 klass = klass->generic_class->container_class;
9153
9154         if (image_is_dynamic (klass->image))
9155                 return lookup_custom_attr (klass->image, klass);
9156
9157         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9158                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9159                 idx <<= MONO_CUSTOM_ATTR_BITS;
9160                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9161         } else {
9162                 idx = mono_metadata_token_index (klass->type_token);
9163                 idx <<= MONO_CUSTOM_ATTR_BITS;
9164                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9165         }
9166         return mono_custom_attrs_from_index (klass->image, idx);
9167 }
9168
9169 MonoCustomAttrInfo*
9170 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9171 {
9172         guint32 idx;
9173         
9174         if (image_is_dynamic (assembly->image))
9175                 return lookup_custom_attr (assembly->image, assembly);
9176         idx = 1; /* there is only one assembly */
9177         idx <<= MONO_CUSTOM_ATTR_BITS;
9178         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9179         return mono_custom_attrs_from_index (assembly->image, idx);
9180 }
9181
9182 static MonoCustomAttrInfo*
9183 mono_custom_attrs_from_module (MonoImage *image)
9184 {
9185         guint32 idx;
9186         
9187         if (image_is_dynamic (image))
9188                 return lookup_custom_attr (image, image);
9189         idx = 1; /* there is only one module */
9190         idx <<= MONO_CUSTOM_ATTR_BITS;
9191         idx |= MONO_CUSTOM_ATTR_MODULE;
9192         return mono_custom_attrs_from_index (image, idx);
9193 }
9194
9195 MonoCustomAttrInfo*
9196 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9197 {
9198         guint32 idx;
9199         
9200         if (image_is_dynamic (klass->image)) {
9201                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9202                 return lookup_custom_attr (klass->image, property);
9203         }
9204         idx = find_property_index (klass, property);
9205         idx <<= MONO_CUSTOM_ATTR_BITS;
9206         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9207         return mono_custom_attrs_from_index (klass->image, idx);
9208 }
9209
9210 MonoCustomAttrInfo*
9211 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9212 {
9213         guint32 idx;
9214         
9215         if (image_is_dynamic (klass->image)) {
9216                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9217                 return lookup_custom_attr (klass->image, event);
9218         }
9219         idx = find_event_index (klass, event);
9220         idx <<= MONO_CUSTOM_ATTR_BITS;
9221         idx |= MONO_CUSTOM_ATTR_EVENT;
9222         return mono_custom_attrs_from_index (klass->image, idx);
9223 }
9224
9225 MonoCustomAttrInfo*
9226 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9227 {
9228         guint32 idx;
9229         if (image_is_dynamic (klass->image)) {
9230                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9231                 return lookup_custom_attr (klass->image, field);
9232         }
9233         idx = find_field_index (klass, field);
9234         idx <<= MONO_CUSTOM_ATTR_BITS;
9235         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9236         return mono_custom_attrs_from_index (klass->image, idx);
9237 }
9238
9239 /**
9240  * mono_custom_attrs_from_param:
9241  * @method: handle to the method that we want to retrieve custom parameter information from
9242  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9243  *
9244  * The result must be released with mono_custom_attrs_free().
9245  *
9246  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9247  */
9248 MonoCustomAttrInfo*
9249 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9250 {
9251         MonoTableInfo *ca;
9252         guint32 i, idx, method_index;
9253         guint32 param_list, param_last, param_pos, found;
9254         MonoImage *image;
9255         MonoReflectionMethodAux *aux;
9256
9257         /*
9258          * An instantiated method has the same cattrs as the generic method definition.
9259          *
9260          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9261          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9262          */
9263         if (method->is_inflated)
9264                 method = ((MonoMethodInflated *) method)->declaring;
9265
9266         if (image_is_dynamic (method->klass->image)) {
9267                 MonoCustomAttrInfo *res, *ainfo;
9268                 int size;
9269
9270                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9271                 if (!aux || !aux->param_cattr)
9272                         return NULL;
9273
9274                 /* Need to copy since it will be freed later */
9275                 ainfo = aux->param_cattr [param];
9276                 if (!ainfo)
9277                         return NULL;
9278                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9279                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9280                 memcpy (res, ainfo, size);
9281                 return res;
9282         }
9283
9284         image = method->klass->image;
9285         method_index = mono_method_get_index (method);
9286         if (!method_index)
9287                 return NULL;
9288         ca = &image->tables [MONO_TABLE_METHOD];
9289
9290         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9291         if (method_index == ca->rows) {
9292                 ca = &image->tables [MONO_TABLE_PARAM];
9293                 param_last = ca->rows + 1;
9294         } else {
9295                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9296                 ca = &image->tables [MONO_TABLE_PARAM];
9297         }
9298         found = FALSE;
9299         for (i = param_list; i < param_last; ++i) {
9300                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9301                 if (param_pos == param) {
9302                         found = TRUE;
9303                         break;
9304                 }
9305         }
9306         if (!found)
9307                 return NULL;
9308         idx = i;
9309         idx <<= MONO_CUSTOM_ATTR_BITS;
9310         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9311         return mono_custom_attrs_from_index (image, idx);
9312 }
9313
9314 gboolean
9315 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9316 {
9317         int i;
9318         MonoClass *klass;
9319         for (i = 0; i < ainfo->num_attrs; ++i) {
9320                 klass = ainfo->attrs [i].ctor->klass;
9321                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9322                         return TRUE;
9323         }
9324         return FALSE;
9325 }
9326
9327 MonoObject*
9328 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9329 {
9330         MonoError error;
9331         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9332         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9333         return res;
9334 }
9335
9336 MonoObject*
9337 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9338 {
9339         int i, attr_index;
9340         MonoClass *klass;
9341         MonoArray *attrs;
9342
9343         mono_error_init (error);
9344
9345         attr_index = -1;
9346         for (i = 0; i < ainfo->num_attrs; ++i) {
9347                 klass = ainfo->attrs [i].ctor->klass;
9348                 if (mono_class_has_parent (klass, attr_klass)) {
9349                         attr_index = i;
9350                         break;
9351                 }
9352         }
9353         if (attr_index == -1)
9354                 return NULL;
9355
9356         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9357         if (!mono_error_ok (error))
9358                 return NULL;
9359         return mono_array_get (attrs, MonoObject*, attr_index);
9360 }
9361
9362 /*
9363  * mono_reflection_get_custom_attrs_info:
9364  * @obj: a reflection object handle
9365  *
9366  * Return the custom attribute info for attributes defined for the
9367  * reflection handle @obj. The objects.
9368  *
9369  * FIXME this function leaks like a sieve for SRE objects.
9370  */
9371 MonoCustomAttrInfo*
9372 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9373 {
9374         MonoClass *klass;
9375         MonoCustomAttrInfo *cinfo = NULL;
9376         
9377         klass = obj->vtable->klass;
9378         if (klass == mono_defaults.monotype_class) {
9379                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9380                 klass = mono_class_from_mono_type (type);
9381                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9382                 cinfo = mono_custom_attrs_from_class (klass);
9383         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9384                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9385                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9386         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9387                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9388                 cinfo = mono_custom_attrs_from_module (module->image);
9389         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9390                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9391                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9392         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9393                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9394                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9395         } else if (strcmp ("MonoField", klass->name) == 0) {
9396                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9397                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9398         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9399                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9400                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9401         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9402                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9403                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9404         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9405                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9406                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9407                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9408                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9409                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9410                 } else if (is_sr_mono_property (member_class)) {
9411                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9412                         MonoMethod *method;
9413                         if (!(method = prop->property->get))
9414                                 method = prop->property->set;
9415                         g_assert (method);
9416
9417                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9418                 } 
9419 #ifndef DISABLE_REFLECTION_EMIT
9420                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9421                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9422                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9423                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9424                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9425                         MonoMethod *method = NULL;
9426                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9427                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9428                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9429                                 method = ((MonoReflectionMethod *)c->cb)->method;
9430                         else
9431                                 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));
9432
9433                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9434                 } 
9435 #endif
9436                 else {
9437                         char *type_name = mono_type_get_full_name (member_class);
9438                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9439                         MonoException *ex = mono_get_exception_not_supported  (msg);
9440                         g_free (type_name);
9441                         g_free (msg);
9442                         mono_raise_exception (ex);
9443                 }
9444         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9445                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9446                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9447         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9448                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9449                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9450         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9451                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9452                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9453         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9454                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9455                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9456         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9457                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9458                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9459         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9460                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9461                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9462         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9463                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9464                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9465         } else { /* handle other types here... */
9466                 g_error ("get custom attrs not yet supported for %s", klass->name);
9467         }
9468
9469         return cinfo;
9470 }
9471
9472 /*
9473  * mono_reflection_get_custom_attrs_by_type:
9474  * @obj: a reflection object handle
9475  *
9476  * Return an array with all the custom attributes defined of the
9477  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9478  * of that type are returned. The objects are fully build. Return NULL if a loading error
9479  * occurs.
9480  */
9481 MonoArray*
9482 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9483 {
9484         MonoArray *result;
9485         MonoCustomAttrInfo *cinfo;
9486
9487         mono_error_init (error);
9488
9489         cinfo = mono_reflection_get_custom_attrs_info (obj);
9490         if (cinfo) {
9491                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9492                 if (!cinfo->cached)
9493                         mono_custom_attrs_free (cinfo);
9494         } else {
9495                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9496                 if (mono_loader_get_last_error ())
9497                         return NULL;
9498                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9499         }
9500
9501         return result;
9502 }
9503
9504 /*
9505  * mono_reflection_get_custom_attrs:
9506  * @obj: a reflection object handle
9507  *
9508  * Return an array with all the custom attributes defined of the
9509  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9510  * occurs.
9511  */
9512 MonoArray*
9513 mono_reflection_get_custom_attrs (MonoObject *obj)
9514 {
9515         MonoError error;
9516
9517         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9518 }
9519
9520 /*
9521  * mono_reflection_get_custom_attrs_data:
9522  * @obj: a reflection obj handle
9523  *
9524  * Returns an array of System.Reflection.CustomAttributeData,
9525  * which include information about attributes reflected on
9526  * types loaded using the Reflection Only methods
9527  */
9528 MonoArray*
9529 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9530 {
9531         MonoArray *result;
9532         MonoCustomAttrInfo *cinfo;
9533
9534         cinfo = mono_reflection_get_custom_attrs_info (obj);
9535         if (cinfo) {
9536                 result = mono_custom_attrs_data_construct (cinfo);
9537                 if (!cinfo->cached)
9538                         mono_custom_attrs_free (cinfo);
9539         } else
9540                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9541
9542         return result;
9543 }
9544
9545 static MonoReflectionType*
9546 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9547 {
9548         static MonoMethod *method_get_underlying_system_type = NULL;
9549         MonoMethod *usertype_method;
9550
9551         if (!method_get_underlying_system_type)
9552                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9553         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9554         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9555 }
9556
9557
9558 static gboolean
9559 is_corlib_type (MonoClass *klass)
9560 {
9561         return klass->image == mono_defaults.corlib;
9562 }
9563
9564 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9565         static MonoClass *cached_class; \
9566         if (cached_class) \
9567                 return cached_class == _class; \
9568         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9569                 cached_class = _class; \
9570                 return TRUE; \
9571         } \
9572         return FALSE; \
9573 } while (0) \
9574
9575
9576 #ifndef DISABLE_REFLECTION_EMIT
9577 static gboolean
9578 is_sre_array (MonoClass *klass)
9579 {
9580         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9581 }
9582
9583 static gboolean
9584 is_sre_byref (MonoClass *klass)
9585 {
9586         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9587 }
9588
9589 static gboolean
9590 is_sre_pointer (MonoClass *klass)
9591 {
9592         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9593 }
9594
9595 static gboolean
9596 is_sre_generic_instance (MonoClass *klass)
9597 {
9598         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9599 }
9600
9601 static gboolean
9602 is_sre_type_builder (MonoClass *klass)
9603 {
9604         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9605 }
9606
9607 static gboolean
9608 is_sre_method_builder (MonoClass *klass)
9609 {
9610         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9611 }
9612
9613 static gboolean
9614 is_sre_ctor_builder (MonoClass *klass)
9615 {
9616         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9617 }
9618
9619 static gboolean
9620 is_sre_field_builder (MonoClass *klass)
9621 {
9622         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9623 }
9624
9625 static gboolean
9626 is_sre_method_on_tb_inst (MonoClass *klass)
9627 {
9628         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9629 }
9630
9631 static gboolean
9632 is_sre_ctor_on_tb_inst (MonoClass *klass)
9633 {
9634         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9635 }
9636
9637 MonoType*
9638 mono_reflection_type_get_handle (MonoReflectionType* ref)
9639 {
9640         MonoClass *klass;
9641         if (!ref)
9642                 return NULL;
9643         if (ref->type)
9644                 return ref->type;
9645
9646         if (is_usertype (ref)) {
9647                 ref = mono_reflection_type_get_underlying_system_type (ref);
9648                 if (ref == NULL || is_usertype (ref))
9649                         return NULL;
9650                 if (ref->type)
9651                         return ref->type;
9652         }
9653
9654         klass = mono_object_class (ref);
9655
9656         if (is_sre_array (klass)) {
9657                 MonoType *res;
9658                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9659                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9660                 g_assert (base);
9661                 if (sre_array->rank == 0) //single dimentional array
9662                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9663                 else
9664                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9665                 sre_array->type.type = res;
9666                 return res;
9667         } else if (is_sre_byref (klass)) {
9668                 MonoType *res;
9669                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9670                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9671                 g_assert (base);
9672                 res = &mono_class_from_mono_type (base)->this_arg;
9673                 sre_byref->type.type = res;
9674                 return res;
9675         } else if (is_sre_pointer (klass)) {
9676                 MonoType *res;
9677                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9678                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9679                 g_assert (base);
9680                 res = &mono_ptr_class_get (base)->byval_arg;
9681                 sre_pointer->type.type = res;
9682                 return res;
9683         } else if (is_sre_generic_instance (klass)) {
9684                 MonoType *res, **types;
9685                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9686                 int i, count;
9687
9688                 count = mono_array_length (gclass->type_arguments);
9689                 types = g_new0 (MonoType*, count);
9690                 for (i = 0; i < count; ++i) {
9691                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
9692                         types [i] = mono_reflection_type_get_handle (t);
9693                         if (!types[i]) {
9694                                 g_free (types);
9695                                 return NULL;
9696                         }
9697                 }
9698
9699                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9700                 g_free (types);
9701                 g_assert (res);
9702                 gclass->type.type = res;
9703                 return res;
9704         }
9705
9706         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9707         return NULL;
9708 }
9709
9710
9711
9712 void
9713 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9714 {
9715         mono_reflection_type_get_handle (type);
9716 }
9717
9718 void
9719 mono_reflection_register_with_runtime (MonoReflectionType *type)
9720 {
9721         MonoType *res = mono_reflection_type_get_handle (type);
9722         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9723         MonoClass *klass;
9724
9725         if (!res)
9726                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9727
9728         klass = mono_class_from_mono_type (res);
9729
9730         mono_loader_lock (); /*same locking as mono_type_get_object*/
9731         mono_domain_lock (domain);
9732
9733         if (!image_is_dynamic (klass->image)) {
9734                 mono_class_setup_supertypes (klass);
9735         } else {
9736                 if (!domain->type_hash)
9737                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9738                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9739                 mono_g_hash_table_insert (domain->type_hash, res, type);
9740         }
9741         mono_domain_unlock (domain);
9742         mono_loader_unlock ();
9743 }
9744
9745 /**
9746  * LOCKING: Assumes the loader lock is held.
9747  */
9748 static MonoMethodSignature*
9749 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9750         MonoMethodSignature *sig;
9751         int count, i;
9752
9753         count = parameters? mono_array_length (parameters): 0;
9754
9755         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9756         sig->param_count = count;
9757         sig->sentinelpos = -1; /* FIXME */
9758         for (i = 0; i < count; ++i)
9759                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9760         return sig;
9761 }
9762
9763 /**
9764  * LOCKING: Assumes the loader lock is held.
9765  */
9766 static MonoMethodSignature*
9767 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9768         MonoMethodSignature *sig;
9769
9770         sig = parameters_to_signature (image, ctor->parameters);
9771         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9772         sig->ret = &mono_defaults.void_class->byval_arg;
9773         return sig;
9774 }
9775
9776 /**
9777  * LOCKING: Assumes the loader lock is held.
9778  */
9779 static MonoMethodSignature*
9780 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9781         MonoMethodSignature *sig;
9782
9783         sig = parameters_to_signature (image, method->parameters);
9784         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9785         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9786         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9787         return sig;
9788 }
9789
9790 static MonoMethodSignature*
9791 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9792         MonoMethodSignature *sig;
9793
9794         sig = parameters_to_signature (NULL, method->parameters);
9795         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9796         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9797         sig->generic_param_count = 0;
9798         return sig;
9799 }
9800
9801 static void
9802 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9803 {
9804         MonoClass *klass = mono_object_class (prop);
9805         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9806                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9807                 *name = mono_string_to_utf8 (pb->name);
9808                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9809         } else {
9810                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9811                 *name = g_strdup (p->property->name);
9812                 if (p->property->get)
9813                         *type = mono_method_signature (p->property->get)->ret;
9814                 else
9815                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9816         }
9817 }
9818
9819 static void
9820 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9821 {
9822         MonoClass *klass = mono_object_class (field);
9823         if (strcmp (klass->name, "FieldBuilder") == 0) {
9824                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9825                 *name = mono_string_to_utf8 (fb->name);
9826                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9827         } else {
9828                 MonoReflectionField *f = (MonoReflectionField *)field;
9829                 *name = g_strdup (mono_field_get_name (f->field));
9830                 *type = f->field->type;
9831         }
9832 }
9833
9834 #else /* DISABLE_REFLECTION_EMIT */
9835
9836 void
9837 mono_reflection_register_with_runtime (MonoReflectionType *type)
9838 {
9839         /* This is empty */
9840 }
9841
9842 static gboolean
9843 is_sre_type_builder (MonoClass *klass)
9844 {
9845         return FALSE;
9846 }
9847
9848 static gboolean
9849 is_sre_generic_instance (MonoClass *klass)
9850 {
9851         return FALSE;
9852 }
9853
9854 static void
9855 init_type_builder_generics (MonoObject *type)
9856 {
9857 }
9858
9859 #endif /* !DISABLE_REFLECTION_EMIT */
9860
9861
9862 static gboolean
9863 is_sr_mono_field (MonoClass *klass)
9864 {
9865         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9866 }
9867
9868 static gboolean
9869 is_sr_mono_property (MonoClass *klass)
9870 {
9871         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9872 }
9873
9874 static gboolean
9875 is_sr_mono_method (MonoClass *klass)
9876 {
9877         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9878 }
9879
9880 static gboolean
9881 is_sr_mono_cmethod (MonoClass *klass)
9882 {
9883         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9884 }
9885
9886 static gboolean
9887 is_sr_mono_generic_method (MonoClass *klass)
9888 {
9889         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9890 }
9891
9892 static gboolean
9893 is_sr_mono_generic_cmethod (MonoClass *klass)
9894 {
9895         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9896 }
9897
9898 gboolean
9899 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9900 {
9901         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9902 }
9903
9904 static gboolean
9905 is_usertype (MonoReflectionType *ref)
9906 {
9907         MonoClass *klass = mono_object_class (ref);
9908         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9909 }
9910
9911 static MonoReflectionType*
9912 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9913 {
9914         if (!type || type->type)
9915                 return type;
9916
9917         if (is_usertype (type)) {
9918                 type = mono_reflection_type_get_underlying_system_type (type);
9919                 if (is_usertype (type))
9920                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9921         }
9922
9923         return type;
9924 }
9925 /*
9926  * Encode a value in a custom attribute stream of bytes.
9927  * The value to encode is either supplied as an object in argument val
9928  * (valuetypes are boxed), or as a pointer to the data in the
9929  * argument argval.
9930  * @type represents the type of the value
9931  * @buffer is the start of the buffer
9932  * @p the current position in the buffer
9933  * @buflen contains the size of the buffer and is used to return the new buffer size
9934  * if this needs to be realloced.
9935  * @retbuffer and @retp return the start and the position of the buffer
9936  */
9937 static void
9938 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9939 {
9940         MonoTypeEnum simple_type;
9941         
9942         if ((p-buffer) + 10 >= *buflen) {
9943                 char *newbuf;
9944                 *buflen *= 2;
9945                 newbuf = (char *)g_realloc (buffer, *buflen);
9946                 p = newbuf + (p-buffer);
9947                 buffer = newbuf;
9948         }
9949         if (!argval)
9950                 argval = ((char*)arg + sizeof (MonoObject));
9951         simple_type = type->type;
9952 handle_enum:
9953         switch (simple_type) {
9954         case MONO_TYPE_BOOLEAN:
9955         case MONO_TYPE_U1:
9956         case MONO_TYPE_I1:
9957                 *p++ = *argval;
9958                 break;
9959         case MONO_TYPE_CHAR:
9960         case MONO_TYPE_U2:
9961         case MONO_TYPE_I2:
9962                 swap_with_size (p, argval, 2, 1);
9963                 p += 2;
9964                 break;
9965         case MONO_TYPE_U4:
9966         case MONO_TYPE_I4:
9967         case MONO_TYPE_R4:
9968                 swap_with_size (p, argval, 4, 1);
9969                 p += 4;
9970                 break;
9971         case MONO_TYPE_R8:
9972                 swap_with_size (p, argval, 8, 1);
9973                 p += 8;
9974                 break;
9975         case MONO_TYPE_U8:
9976         case MONO_TYPE_I8:
9977                 swap_with_size (p, argval, 8, 1);
9978                 p += 8;
9979                 break;
9980         case MONO_TYPE_VALUETYPE:
9981                 if (type->data.klass->enumtype) {
9982                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9983                         goto handle_enum;
9984                 } else {
9985                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9986                 }
9987                 break;
9988         case MONO_TYPE_STRING: {
9989                 char *str;
9990                 guint32 slen;
9991                 if (!arg) {
9992                         *p++ = 0xFF;
9993                         break;
9994                 }
9995                 str = mono_string_to_utf8 ((MonoString*)arg);
9996                 slen = strlen (str);
9997                 if ((p-buffer) + 10 + slen >= *buflen) {
9998                         char *newbuf;
9999                         *buflen *= 2;
10000                         *buflen += slen;
10001                         newbuf = (char *)g_realloc (buffer, *buflen);
10002                         p = newbuf + (p-buffer);
10003                         buffer = newbuf;
10004                 }
10005                 mono_metadata_encode_value (slen, p, &p);
10006                 memcpy (p, str, slen);
10007                 p += slen;
10008                 g_free (str);
10009                 break;
10010         }
10011         case MONO_TYPE_CLASS: {
10012                 char *str;
10013                 guint32 slen;
10014                 if (!arg) {
10015                         *p++ = 0xFF;
10016                         break;
10017                 }
10018 handle_type:
10019                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10020                 slen = strlen (str);
10021                 if ((p-buffer) + 10 + slen >= *buflen) {
10022                         char *newbuf;
10023                         *buflen *= 2;
10024                         *buflen += slen;
10025                         newbuf = (char *)g_realloc (buffer, *buflen);
10026                         p = newbuf + (p-buffer);
10027                         buffer = newbuf;
10028                 }
10029                 mono_metadata_encode_value (slen, p, &p);
10030                 memcpy (p, str, slen);
10031                 p += slen;
10032                 g_free (str);
10033                 break;
10034         }
10035         case MONO_TYPE_SZARRAY: {
10036                 int len, i;
10037                 MonoClass *eclass, *arg_eclass;
10038
10039                 if (!arg) {
10040                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10041                         break;
10042                 }
10043                 len = mono_array_length ((MonoArray*)arg);
10044                 *p++ = len & 0xff;
10045                 *p++ = (len >> 8) & 0xff;
10046                 *p++ = (len >> 16) & 0xff;
10047                 *p++ = (len >> 24) & 0xff;
10048                 *retp = p;
10049                 *retbuffer = buffer;
10050                 eclass = type->data.klass;
10051                 arg_eclass = mono_object_class (arg)->element_class;
10052
10053                 if (!eclass) {
10054                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10055                         eclass = mono_defaults.object_class;
10056                 }
10057                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10058                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10059                         int elsize = mono_class_array_element_size (arg_eclass);
10060                         for (i = 0; i < len; ++i) {
10061                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10062                                 elptr += elsize;
10063                         }
10064                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10065                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10066                         int elsize = mono_class_array_element_size (eclass);
10067                         for (i = 0; i < len; ++i) {
10068                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10069                                 elptr += elsize;
10070                         }
10071                 } else {
10072                         for (i = 0; i < len; ++i) {
10073                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10074                         }
10075                 }
10076                 break;
10077         }
10078         case MONO_TYPE_OBJECT: {
10079                 MonoClass *klass;
10080                 char *str;
10081                 guint32 slen;
10082
10083                 /*
10084                  * The parameter type is 'object' but the type of the actual
10085                  * argument is not. So we have to add type information to the blob
10086                  * too. This is completely undocumented in the spec.
10087                  */
10088
10089                 if (arg == NULL) {
10090                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10091                         *p++ = 0xFF;
10092                         break;
10093                 }
10094                 
10095                 klass = mono_object_class (arg);
10096
10097                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10098                         *p++ = 0x50;
10099                         goto handle_type;
10100                 } else if (klass->enumtype) {
10101                         *p++ = 0x55;
10102                 } else if (klass == mono_defaults.string_class) {
10103                         simple_type = MONO_TYPE_STRING;
10104                         *p++ = 0x0E;
10105                         goto handle_enum;
10106                 } else if (klass->rank == 1) {
10107                         *p++ = 0x1D;
10108                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10109                                 /* See Partition II, Appendix B3 */
10110                                 *p++ = 0x51;
10111                         else
10112                                 *p++ = klass->element_class->byval_arg.type;
10113                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10114                         break;
10115                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10116                         *p++ = simple_type = klass->byval_arg.type;
10117                         goto handle_enum;
10118                 } else {
10119                         g_error ("unhandled type in custom attr");
10120                 }
10121                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10122                 slen = strlen (str);
10123                 if ((p-buffer) + 10 + slen >= *buflen) {
10124                         char *newbuf;
10125                         *buflen *= 2;
10126                         *buflen += slen;
10127                         newbuf = (char *)g_realloc (buffer, *buflen);
10128                         p = newbuf + (p-buffer);
10129                         buffer = newbuf;
10130                 }
10131                 mono_metadata_encode_value (slen, p, &p);
10132                 memcpy (p, str, slen);
10133                 p += slen;
10134                 g_free (str);
10135                 simple_type = mono_class_enum_basetype (klass)->type;
10136                 goto handle_enum;
10137         }
10138         default:
10139                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10140         }
10141         *retp = p;
10142         *retbuffer = buffer;
10143 }
10144
10145 static void
10146 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10147 {
10148         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10149                 char *str = type_get_qualified_name (type, NULL);
10150                 int slen = strlen (str);
10151
10152                 *p++ = 0x55;
10153                 /*
10154                  * This seems to be optional...
10155                  * *p++ = 0x80;
10156                  */
10157                 mono_metadata_encode_value (slen, p, &p);
10158                 memcpy (p, str, slen);
10159                 p += slen;
10160                 g_free (str);
10161         } else if (type->type == MONO_TYPE_OBJECT) {
10162                 *p++ = 0x51;
10163         } else if (type->type == MONO_TYPE_CLASS) {
10164                 /* it should be a type: encode_cattr_value () has the check */
10165                 *p++ = 0x50;
10166         } else {
10167                 mono_metadata_encode_value (type->type, p, &p);
10168                 if (type->type == MONO_TYPE_SZARRAY)
10169                         /* See the examples in Partition VI, Annex B */
10170                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10171         }
10172
10173         *retp = p;
10174 }
10175
10176 #ifndef DISABLE_REFLECTION_EMIT
10177 static void
10178 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10179 {
10180         int len;
10181         /* Preallocate a large enough buffer */
10182         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10183                 char *str = type_get_qualified_name (type, NULL);
10184                 len = strlen (str);
10185                 g_free (str);
10186         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10187                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10188                 len = strlen (str);
10189                 g_free (str);
10190         } else {
10191                 len = 0;
10192         }
10193         len += strlen (name);
10194
10195         if ((p-buffer) + 20 + len >= *buflen) {
10196                 char *newbuf;
10197                 *buflen *= 2;
10198                 *buflen += len;
10199                 newbuf = (char *)g_realloc (buffer, *buflen);
10200                 p = newbuf + (p-buffer);
10201                 buffer = newbuf;
10202         }
10203
10204         encode_field_or_prop_type (type, p, &p);
10205
10206         len = strlen (name);
10207         mono_metadata_encode_value (len, p, &p);
10208         memcpy (p, name, len);
10209         p += len;
10210         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10211         *retp = p;
10212         *retbuffer = buffer;
10213 }
10214
10215 /*
10216  * mono_reflection_get_custom_attrs_blob:
10217  * @ctor: custom attribute constructor
10218  * @ctorArgs: arguments o the constructor
10219  * @properties:
10220  * @propValues:
10221  * @fields:
10222  * @fieldValues:
10223  * 
10224  * Creates the blob of data that needs to be saved in the metadata and that represents
10225  * the custom attributed described by @ctor, @ctorArgs etc.
10226  * Returns: a Byte array representing the blob of data.
10227  */
10228 MonoArray*
10229 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10230 {
10231         MonoArray *result;
10232         MonoMethodSignature *sig;
10233         MonoObject *arg;
10234         char *buffer, *p;
10235         guint32 buflen, i;
10236
10237         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10238                 /* sig is freed later so allocate it in the heap */
10239                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10240         } else {
10241                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10242         }
10243
10244         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10245         buflen = 256;
10246         p = buffer = (char *)g_malloc (buflen);
10247         /* write the prolog */
10248         *p++ = 1;
10249         *p++ = 0;
10250         for (i = 0; i < sig->param_count; ++i) {
10251                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10252                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10253         }
10254         i = 0;
10255         if (properties)
10256                 i += mono_array_length (properties);
10257         if (fields)
10258                 i += mono_array_length (fields);
10259         *p++ = i & 0xff;
10260         *p++ = (i >> 8) & 0xff;
10261         if (properties) {
10262                 MonoObject *prop;
10263                 for (i = 0; i < mono_array_length (properties); ++i) {
10264                         MonoType *ptype;
10265                         char *pname;
10266
10267                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10268                         get_prop_name_and_type (prop, &pname, &ptype);
10269                         *p++ = 0x54; /* PROPERTY signature */
10270                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10271                         g_free (pname);
10272                 }
10273         }
10274
10275         if (fields) {
10276                 MonoObject *field;
10277                 for (i = 0; i < mono_array_length (fields); ++i) {
10278                         MonoType *ftype;
10279                         char *fname;
10280
10281                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10282                         get_field_name_and_type (field, &fname, &ftype);
10283                         *p++ = 0x53; /* FIELD signature */
10284                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10285                         g_free (fname);
10286                 }
10287         }
10288
10289         g_assert (p - buffer <= buflen);
10290         buflen = p - buffer;
10291         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10292         p = mono_array_addr (result, char, 0);
10293         memcpy (p, buffer, buflen);
10294         g_free (buffer);
10295         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10296                 g_free (sig);
10297         return result;
10298 }
10299
10300 /*
10301  * mono_reflection_setup_internal_class:
10302  * @tb: a TypeBuilder object
10303  *
10304  * Creates a MonoClass that represents the TypeBuilder.
10305  * This is a trick that lets us simplify a lot of reflection code
10306  * (and will allow us to support Build and Run assemblies easier).
10307  */
10308 void
10309 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10310 {
10311         MonoError error;
10312         MonoClass *klass, *parent;
10313
10314         RESOLVE_TYPE (tb->parent);
10315
10316         mono_loader_lock ();
10317
10318         if (tb->parent) {
10319                 /* check so we can compile corlib correctly */
10320                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10321                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10322                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10323                 } else {
10324                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10325                 }
10326         } else {
10327                 parent = NULL;
10328         }
10329         
10330         /* the type has already being created: it means we just have to change the parent */
10331         if (tb->type.type) {
10332                 klass = mono_class_from_mono_type (tb->type.type);
10333                 klass->parent = NULL;
10334                 /* fool mono_class_setup_parent */
10335                 klass->supertypes = NULL;
10336                 mono_class_setup_parent (klass, parent);
10337                 mono_class_setup_mono_type (klass);
10338                 mono_loader_unlock ();
10339                 return;
10340         }
10341
10342         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10343
10344         klass->image = &tb->module->dynamic_image->image;
10345
10346         klass->inited = 1; /* we lie to the runtime */
10347         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10348         if (!mono_error_ok (&error))
10349                 goto failure;
10350         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10351         if (!mono_error_ok (&error))
10352                 goto failure;
10353         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10354         klass->flags = tb->attrs;
10355         
10356         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10357
10358         klass->element_class = klass;
10359
10360         if (mono_class_get_ref_info (klass) == NULL) {
10361
10362                 mono_class_set_ref_info (klass, tb);
10363
10364                 /* Put into cache so mono_class_get_checked () will find it.
10365                 Skip nested types as those should not be available on the global scope. */
10366                 if (!tb->nesting_type)
10367                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10368
10369                 /*
10370                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10371                 by performing a mono_class_get which does the full resolution.
10372
10373                 Working around this semantics would require us to write a lot of code for no clear advantage.
10374                 */
10375                 mono_image_append_class_to_reflection_info_set (klass);
10376         } else {
10377                 g_assert (mono_class_get_ref_info (klass) == tb);
10378         }
10379
10380         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10381
10382         if (parent != NULL) {
10383                 mono_class_setup_parent (klass, parent);
10384         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10385                 const char *old_n = klass->name;
10386                 /* trick to get relative numbering right when compiling corlib */
10387                 klass->name = "BuildingObject";
10388                 mono_class_setup_parent (klass, mono_defaults.object_class);
10389                 klass->name = old_n;
10390         }
10391
10392         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10393                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10394                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10395                 klass->instance_size = sizeof (MonoObject);
10396                 klass->size_inited = 1;
10397                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10398         }
10399
10400         mono_class_setup_mono_type (klass);
10401
10402         mono_class_setup_supertypes (klass);
10403
10404         /*
10405          * FIXME: handle interfaces.
10406          */
10407
10408         tb->type.type = &klass->byval_arg;
10409
10410         if (tb->nesting_type) {
10411                 g_assert (tb->nesting_type->type);
10412                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10413         }
10414
10415         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10416
10417         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10418         
10419         mono_loader_unlock ();
10420         return;
10421
10422 failure:
10423         mono_loader_unlock ();
10424         mono_error_raise_exception (&error);
10425 }
10426
10427 /*
10428  * mono_reflection_setup_generic_class:
10429  * @tb: a TypeBuilder object
10430  *
10431  * Setup the generic class before adding the first generic parameter.
10432  */
10433 void
10434 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10435 {
10436 }
10437
10438 /*
10439  * mono_reflection_create_generic_class:
10440  * @tb: a TypeBuilder object
10441  *
10442  * Creates the generic class after all generic parameters have been added.
10443  */
10444 void
10445 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10446 {
10447         MonoClass *klass;
10448         int count, i;
10449
10450         klass = mono_class_from_mono_type (tb->type.type);
10451
10452         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10453
10454         if (klass->generic_container || (count == 0))
10455                 return;
10456
10457         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10458
10459         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10460
10461         klass->generic_container->owner.klass = klass;
10462         klass->generic_container->type_argc = count;
10463         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10464
10465         klass->is_generic = 1;
10466
10467         for (i = 0; i < count; i++) {
10468                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10469                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10470                 klass->generic_container->type_params [i] = *param;
10471                 /*Make sure we are a diferent type instance */
10472                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10473                 klass->generic_container->type_params [i].info.pklass = NULL;
10474                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10475
10476                 g_assert (klass->generic_container->type_params [i].param.owner);
10477         }
10478
10479         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10480 }
10481
10482 /*
10483  * mono_reflection_create_internal_class:
10484  * @tb: a TypeBuilder object
10485  *
10486  * Actually create the MonoClass that is associated with the TypeBuilder.
10487  */
10488 void
10489 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10490 {
10491         MonoClass *klass;
10492
10493         klass = mono_class_from_mono_type (tb->type.type);
10494
10495         mono_loader_lock ();
10496         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10497                 MonoReflectionFieldBuilder *fb;
10498                 MonoClass *ec;
10499                 MonoType *enum_basetype;
10500
10501                 g_assert (tb->fields != NULL);
10502                 g_assert (mono_array_length (tb->fields) >= 1);
10503
10504                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10505
10506                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10507                         mono_loader_unlock ();
10508                         return;
10509                 }
10510
10511                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10512                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10513                 if (!klass->element_class)
10514                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10515
10516                 /*
10517                  * get the element_class from the current corlib.
10518                  */
10519                 ec = default_class_from_mono_type (enum_basetype);
10520                 klass->instance_size = ec->instance_size;
10521                 klass->size_inited = 1;
10522                 /* 
10523                  * this is almost safe to do with enums and it's needed to be able
10524                  * to create objects of the enum type (for use in SetConstant).
10525                  */
10526                 /* FIXME: Does this mean enums can't have method overrides ? */
10527                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10528         }
10529         mono_loader_unlock ();
10530 }
10531
10532 static MonoMarshalSpec*
10533 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10534                                                                 MonoReflectionMarshal *minfo)
10535 {
10536         MonoMarshalSpec *res;
10537
10538         res = image_g_new0 (image, MonoMarshalSpec, 1);
10539         res->native = (MonoMarshalNative)minfo->type;
10540
10541         switch (minfo->type) {
10542         case MONO_NATIVE_LPARRAY:
10543                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
10544                 if (minfo->has_size) {
10545                         res->data.array_data.param_num = minfo->param_num;
10546                         res->data.array_data.num_elem = minfo->count;
10547                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10548                 }
10549                 else {
10550                         res->data.array_data.param_num = -1;
10551                         res->data.array_data.num_elem = -1;
10552                         res->data.array_data.elem_mult = -1;
10553                 }
10554                 break;
10555
10556         case MONO_NATIVE_BYVALTSTR:
10557         case MONO_NATIVE_BYVALARRAY:
10558                 res->data.array_data.num_elem = minfo->count;
10559                 break;
10560
10561         case MONO_NATIVE_CUSTOM:
10562                 if (minfo->marshaltyperef)
10563                         res->data.custom_data.custom_name =
10564                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10565                 if (minfo->mcookie)
10566                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10567                 break;
10568
10569         default:
10570                 break;
10571         }
10572
10573         return res;
10574 }
10575 #endif /* !DISABLE_REFLECTION_EMIT */
10576
10577 MonoReflectionMarshalAsAttribute*
10578 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10579                                                                                    MonoMarshalSpec *spec)
10580 {
10581         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10582         MonoReflectionMarshalAsAttribute *minfo;
10583         MonoType *mtype;
10584
10585         if (!System_Reflection_Emit_MarshalAsAttribute) {
10586                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10587                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10588                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10589         }
10590
10591         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10592         minfo->utype = spec->native;
10593
10594         switch (minfo->utype) {
10595         case MONO_NATIVE_LPARRAY:
10596                 minfo->array_subtype = spec->data.array_data.elem_type;
10597                 minfo->size_const = spec->data.array_data.num_elem;
10598                 if (spec->data.array_data.param_num != -1)
10599                         minfo->size_param_index = spec->data.array_data.param_num;
10600                 break;
10601
10602         case MONO_NATIVE_BYVALTSTR:
10603         case MONO_NATIVE_BYVALARRAY:
10604                 minfo->size_const = spec->data.array_data.num_elem;
10605                 break;
10606
10607         case MONO_NATIVE_CUSTOM:
10608                 if (spec->data.custom_data.custom_name) {
10609                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10610                         if (mtype)
10611                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10612
10613                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10614                 }
10615                 if (spec->data.custom_data.cookie)
10616                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10617                 break;
10618
10619         default:
10620                 break;
10621         }
10622
10623         return minfo;
10624 }
10625
10626 #ifndef DISABLE_REFLECTION_EMIT
10627 static MonoMethod*
10628 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10629                                          ReflectionMethodBuilder *rmb,
10630                                          MonoMethodSignature *sig)
10631 {
10632         MonoError error;
10633         MonoMethod *m;
10634         MonoMethodWrapper *wrapperm;
10635         MonoMarshalSpec **specs;
10636         MonoReflectionMethodAux *method_aux;
10637         MonoImage *image;
10638         gboolean dynamic;
10639         int i;
10640
10641         mono_error_init (&error);
10642         /*
10643          * Methods created using a MethodBuilder should have their memory allocated
10644          * inside the image mempool, while dynamic methods should have their memory
10645          * malloc'd.
10646          */
10647         dynamic = rmb->refs != NULL;
10648         image = dynamic ? NULL : klass->image;
10649
10650         if (!dynamic)
10651                 g_assert (!klass->generic_class);
10652
10653         mono_loader_lock ();
10654
10655         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10656                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10657                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10658         else
10659                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10660
10661         wrapperm = (MonoMethodWrapper*)m;
10662
10663         m->dynamic = dynamic;
10664         m->slot = -1;
10665         m->flags = rmb->attrs;
10666         m->iflags = rmb->iattrs;
10667         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10668         m->klass = klass;
10669         m->signature = sig;
10670         m->sre_method = TRUE;
10671         m->skip_visibility = rmb->skip_visibility;
10672         if (rmb->table_idx)
10673                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10674
10675         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10676                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10677                         m->string_ctor = 1;
10678
10679                 m->signature->pinvoke = 1;
10680         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10681                 m->signature->pinvoke = 1;
10682
10683                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10684
10685                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10686                 g_assert (mono_error_ok (&error));
10687                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10688                 g_assert (mono_error_ok (&error));
10689                 
10690                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10691
10692                 if (image_is_dynamic (klass->image))
10693                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10694
10695                 mono_loader_unlock ();
10696
10697                 return m;
10698         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10699                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10700                 MonoMethodHeader *header;
10701                 guint32 code_size;
10702                 gint32 max_stack, i;
10703                 gint32 num_locals = 0;
10704                 gint32 num_clauses = 0;
10705                 guint8 *code;
10706
10707                 if (rmb->ilgen) {
10708                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10709                         code_size = rmb->ilgen->code_len;
10710                         max_stack = rmb->ilgen->max_stack;
10711                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10712                         if (rmb->ilgen->ex_handlers)
10713                                 num_clauses = method_count_clauses (rmb->ilgen);
10714                 } else {
10715                         if (rmb->code) {
10716                                 code = mono_array_addr (rmb->code, guint8, 0);
10717                                 code_size = mono_array_length (rmb->code);
10718                                 /* we probably need to run a verifier on the code... */
10719                                 max_stack = 8; 
10720                         }
10721                         else {
10722                                 code = NULL;
10723                                 code_size = 0;
10724                                 max_stack = 8;
10725                         }
10726                 }
10727
10728                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10729                 header->code_size = code_size;
10730                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
10731                 memcpy ((char*)header->code, code, code_size);
10732                 header->max_stack = max_stack;
10733                 header->init_locals = rmb->init_locals;
10734                 header->num_locals = num_locals;
10735
10736                 for (i = 0; i < num_locals; ++i) {
10737                         MonoReflectionLocalBuilder *lb = 
10738                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10739
10740                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10741                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10742                 }
10743
10744                 header->num_clauses = num_clauses;
10745                 if (num_clauses) {
10746                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10747                                  rmb->ilgen, num_clauses);
10748                 }
10749
10750                 wrapperm->header = header;
10751         }
10752
10753         if (rmb->generic_params) {
10754                 int count = mono_array_length (rmb->generic_params);
10755                 MonoGenericContainer *container = rmb->generic_container;
10756
10757                 g_assert (container);
10758
10759                 container->type_argc = count;
10760                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10761                 container->owner.method = m;
10762                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
10763
10764                 m->is_generic = TRUE;
10765                 mono_method_set_generic_container (m, container);
10766
10767                 for (i = 0; i < count; i++) {
10768                         MonoReflectionGenericParam *gp =
10769                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10770                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10771                         container->type_params [i] = *param;
10772                 }
10773
10774                 /*
10775                  * The method signature might have pointers to generic parameters that belong to other methods.
10776                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10777                  * generic parameters.
10778                  */
10779                 for (i = 0; i < m->signature->param_count; ++i) {
10780                         MonoType *t = m->signature->params [i];
10781                         if (t->type == MONO_TYPE_MVAR) {
10782                                 MonoGenericParam *gparam =  t->data.generic_param;
10783                                 if (gparam->num < count) {
10784                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10785                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10786                                 }
10787
10788                         }
10789                 }
10790
10791                 if (klass->generic_container) {
10792                         container->parent = klass->generic_container;
10793                         container->context.class_inst = klass->generic_container->context.class_inst;
10794                 }
10795                 container->context.method_inst = mono_get_shared_generic_inst (container);
10796         }
10797
10798         if (rmb->refs) {
10799                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10800                 int i;
10801                 void **data;
10802
10803                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10804
10805                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10806                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10807                 for (i = 0; i < rmb->nrefs; ++i)
10808                         data [i + 1] = rmb->refs [i];
10809         }
10810
10811         method_aux = NULL;
10812
10813         /* Parameter info */
10814         if (rmb->pinfo) {
10815                 if (!method_aux)
10816                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10817                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10818                 for (i = 0; i <= m->signature->param_count; ++i) {
10819                         MonoReflectionParamBuilder *pb;
10820                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10821                                 if ((i > 0) && (pb->attrs)) {
10822                                         /* Make a copy since it might point to a shared type structure */
10823                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10824                                         m->signature->params [i - 1]->attrs = pb->attrs;
10825                                 }
10826
10827                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10828                                         MonoDynamicImage *assembly;
10829                                         guint32 idx, len;
10830                                         MonoTypeEnum def_type;
10831                                         char *p;
10832                                         const char *p2;
10833
10834                                         if (!method_aux->param_defaults) {
10835                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10836                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10837                                         }
10838                                         assembly = (MonoDynamicImage*)klass->image;
10839                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10840                                         /* Copy the data from the blob since it might get realloc-ed */
10841                                         p = assembly->blob.data + idx;
10842                                         len = mono_metadata_decode_blob_size (p, &p2);
10843                                         len += p2 - p;
10844                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
10845                                         method_aux->param_default_types [i] = def_type;
10846                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10847                                 }
10848
10849                                 if (pb->name) {
10850                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10851                                         g_assert (mono_error_ok (&error));
10852                                 }
10853                                 if (pb->cattrs) {
10854                                         if (!method_aux->param_cattr)
10855                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10856                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10857                                 }
10858                         }
10859                 }
10860         }
10861
10862         /* Parameter marshalling */
10863         specs = NULL;
10864         if (rmb->pinfo)         
10865                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10866                         MonoReflectionParamBuilder *pb;
10867                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10868                                 if (pb->marshal_info) {
10869                                         if (specs == NULL)
10870                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10871                                         specs [pb->position] = 
10872                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10873                                 }
10874                         }
10875                 }
10876         if (specs != NULL) {
10877                 if (!method_aux)
10878                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10879                 method_aux->param_marshall = specs;
10880         }
10881
10882         if (image_is_dynamic (klass->image) && method_aux)
10883                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10884
10885         mono_loader_unlock ();
10886
10887         return m;
10888 }       
10889
10890 static MonoMethod*
10891 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10892 {
10893         ReflectionMethodBuilder rmb;
10894         MonoMethodSignature *sig;
10895
10896         mono_loader_lock ();
10897         sig = ctor_builder_to_signature (klass->image, mb);
10898         mono_loader_unlock ();
10899
10900         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10901
10902         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10903         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10904
10905         /* If we are in a generic class, we might be called multiple times from inflate_method */
10906         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10907                 /* ilgen is no longer needed */
10908                 mb->ilgen = NULL;
10909         }
10910
10911         return mb->mhandle;
10912 }
10913
10914 static MonoMethod*
10915 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10916 {
10917         ReflectionMethodBuilder rmb;
10918         MonoMethodSignature *sig;
10919
10920         mono_loader_lock ();
10921         sig = method_builder_to_signature (klass->image, mb);
10922         mono_loader_unlock ();
10923
10924         reflection_methodbuilder_from_method_builder (&rmb, mb);
10925
10926         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10927         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10928
10929         /* If we are in a generic class, we might be called multiple times from inflate_method */
10930         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10931                 /* ilgen is no longer needed */
10932                 mb->ilgen = NULL;
10933         }
10934         return mb->mhandle;
10935 }
10936
10937 static MonoClassField*
10938 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10939 {
10940         MonoClassField *field;
10941         MonoType *custom;
10942         MonoError error;
10943
10944         field = g_new0 (MonoClassField, 1);
10945
10946         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10947         g_assert (mono_error_ok (&error));
10948         if (fb->attrs || fb->modreq || fb->modopt) {
10949                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10950                 field->type->attrs = fb->attrs;
10951
10952                 g_assert (image_is_dynamic (klass->image));
10953                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10954                 g_free (field->type);
10955                 field->type = mono_metadata_type_dup (klass->image, custom);
10956                 g_free (custom);
10957         } else {
10958                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10959         }
10960         if (fb->offset != -1)
10961                 field->offset = fb->offset;
10962         field->parent = klass;
10963         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10964
10965         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10966
10967         return field;
10968 }
10969 #endif
10970
10971 MonoType*
10972 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10973 {
10974         MonoClass *klass;
10975         MonoReflectionTypeBuilder *tb = NULL;
10976         gboolean is_dynamic = FALSE;
10977         MonoClass *geninst;
10978
10979         mono_loader_lock ();
10980
10981         if (is_sre_type_builder (mono_object_class (type))) {
10982                 tb = (MonoReflectionTypeBuilder *) type;
10983
10984                 is_dynamic = TRUE;
10985         } else if (is_sre_generic_instance (mono_object_class (type))) {
10986                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10987                 MonoReflectionType *gtd = rgi->generic_type;
10988
10989                 if (is_sre_type_builder (mono_object_class (gtd))) {
10990                         tb = (MonoReflectionTypeBuilder *)gtd;
10991                         is_dynamic = TRUE;
10992                 }
10993         }
10994
10995         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10996         if (tb && tb->generic_container)
10997                 mono_reflection_create_generic_class (tb);
10998
10999         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11000         if (!klass->generic_container) {
11001                 mono_loader_unlock ();
11002                 return NULL;
11003         }
11004
11005         if (klass->wastypebuilder) {
11006                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11007
11008                 is_dynamic = TRUE;
11009         }
11010
11011         mono_loader_unlock ();
11012
11013         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11014
11015         return &geninst->byval_arg;
11016 }
11017
11018 MonoClass*
11019 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11020 {
11021         MonoGenericClass *gclass;
11022         MonoGenericInst *inst;
11023
11024         g_assert (klass->generic_container);
11025
11026         inst = mono_metadata_get_generic_inst (type_argc, types);
11027         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11028
11029         return mono_generic_class_get_class (gclass);
11030 }
11031
11032 MonoReflectionMethod*
11033 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11034 {
11035         MonoError error;
11036         MonoClass *klass;
11037         MonoMethod *method, *inflated;
11038         MonoMethodInflated *imethod;
11039         MonoGenericContext tmp_context;
11040         MonoGenericInst *ginst;
11041         MonoType **type_argv;
11042         int count, i;
11043
11044         /*FIXME but this no longer should happen*/
11045         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11046 #ifndef DISABLE_REFLECTION_EMIT
11047                 MonoReflectionMethodBuilder *mb = NULL;
11048                 MonoReflectionTypeBuilder *tb;
11049                 MonoClass *klass;
11050
11051                 mb = (MonoReflectionMethodBuilder *) rmethod;
11052                 tb = (MonoReflectionTypeBuilder *) mb->type;
11053                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11054
11055                 method = methodbuilder_to_mono_method (klass, mb);
11056 #else
11057                 g_assert_not_reached ();
11058                 method = NULL;
11059 #endif
11060         } else {
11061                 method = rmethod->method;
11062         }
11063
11064         klass = method->klass;
11065
11066         if (method->is_inflated)
11067                 method = ((MonoMethodInflated *) method)->declaring;
11068
11069         count = mono_method_signature (method)->generic_param_count;
11070         if (count != mono_array_length (types))
11071                 return NULL;
11072
11073         type_argv = g_new0 (MonoType *, count);
11074         for (i = 0; i < count; i++) {
11075                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11076                 type_argv [i] = mono_reflection_type_get_handle (garg);
11077         }
11078         ginst = mono_metadata_get_generic_inst (count, type_argv);
11079         g_free (type_argv);
11080
11081         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11082         tmp_context.method_inst = ginst;
11083
11084         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11085         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11086         imethod = (MonoMethodInflated *) inflated;
11087
11088         /*FIXME but I think this is no longer necessary*/
11089         if (image_is_dynamic (method->klass->image)) {
11090                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11091                 /*
11092                  * This table maps metadata structures representing inflated methods/fields
11093                  * to the reflection objects representing their generic definitions.
11094                  */
11095                 mono_image_lock ((MonoImage*)image);
11096                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11097                 mono_image_unlock ((MonoImage*)image);
11098         }
11099
11100         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11101                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11102         
11103         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11104 }
11105
11106 #ifndef DISABLE_REFLECTION_EMIT
11107
11108 static MonoMethod *
11109 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11110 {
11111         MonoMethodInflated *imethod;
11112         MonoGenericContext *context;
11113         int i;
11114
11115         /*
11116          * With generic code sharing the klass might not be inflated.
11117          * This can happen because classes inflated with their own
11118          * type arguments are "normalized" to the uninflated class.
11119          */
11120         if (!klass->generic_class)
11121                 return method;
11122
11123         context = mono_class_get_context (klass);
11124
11125         if (klass->method.count && klass->methods) {
11126                 /* Find the already created inflated method */
11127                 for (i = 0; i < klass->method.count; ++i) {
11128                         g_assert (klass->methods [i]->is_inflated);
11129                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11130                                 break;
11131                 }
11132                 g_assert (i < klass->method.count);
11133                 imethod = (MonoMethodInflated*)klass->methods [i];
11134         } else {
11135                 MonoError error;
11136                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11137                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11138         }
11139
11140         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11141                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11142
11143                 mono_image_lock ((MonoImage*)image);
11144                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11145                 mono_image_unlock ((MonoImage*)image);
11146         }
11147         return (MonoMethod *) imethod;
11148 }
11149
11150 static MonoMethod *
11151 inflate_method (MonoReflectionType *type, MonoObject *obj)
11152 {
11153         MonoMethod *method;
11154         MonoClass *gklass;
11155
11156         MonoClass *type_class = mono_object_class (type);
11157
11158         if (is_sre_generic_instance (type_class)) {
11159                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11160                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11161         } else if (is_sre_type_builder (type_class)) {
11162                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11163         } else if (type->type) {
11164                 gklass = mono_class_from_mono_type (type->type);
11165                 gklass = mono_class_get_generic_type_definition (gklass);
11166         } else {
11167                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11168         }
11169
11170         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11171                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11172                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11173                 else
11174                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11175         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11176                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11177         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11178                 method = ((MonoReflectionMethod *) obj)->method;
11179         else {
11180                 method = NULL; /* prevent compiler warning */
11181                 g_error ("can't handle type %s", obj->vtable->klass->name);
11182         }
11183
11184         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11185 }
11186
11187 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11188 void
11189 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11190 {
11191         MonoGenericClass *gclass;
11192         MonoDynamicGenericClass *dgclass;
11193         MonoClass *klass, *gklass;
11194         MonoType *gtype;
11195         int i;
11196
11197         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11198         klass = mono_class_from_mono_type (gtype);
11199         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11200         gclass = gtype->data.generic_class;
11201
11202         if (!gclass->is_dynamic)
11203                 return;
11204
11205         dgclass = (MonoDynamicGenericClass *) gclass;
11206
11207         if (dgclass->initialized)
11208                 return;
11209
11210         gklass = gclass->container_class;
11211         mono_class_init (gklass);
11212
11213         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11214
11215         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11216         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11217         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11218
11219         for (i = 0; i < dgclass->count_fields; i++) {
11220                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11221                 MonoClassField *field, *inflated_field = NULL;
11222
11223                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11224                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11225                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11226                         field = ((MonoReflectionField *) obj)->field;
11227                 else {
11228                         field = NULL; /* prevent compiler warning */
11229                         g_assert_not_reached ();
11230                 }
11231
11232                 dgclass->fields [i] = *field;
11233                 dgclass->fields [i].parent = klass;
11234                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11235                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11236                 dgclass->field_generic_types [i] = field->type;
11237                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11238                 dgclass->field_objects [i] = obj;
11239
11240                 if (inflated_field) {
11241                         g_free (inflated_field);
11242                 } else {
11243                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11244                 }
11245         }
11246
11247         dgclass->initialized = TRUE;
11248 }
11249
11250 void
11251 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11252 {
11253         MonoDynamicGenericClass *dgclass;
11254         int i;
11255
11256         g_assert (gclass->is_dynamic);
11257
11258         dgclass = (MonoDynamicGenericClass *)gclass;
11259
11260         for (i = 0; i < dgclass->count_fields; ++i) {
11261                 MonoClassField *field = dgclass->fields + i;
11262                 mono_metadata_free_type (field->type);
11263                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11264         }
11265 }
11266
11267 static void
11268 fix_partial_generic_class (MonoClass *klass)
11269 {
11270         MonoClass *gklass = klass->generic_class->container_class;
11271         MonoDynamicGenericClass *dgclass;
11272         int i;
11273
11274         if (klass->wastypebuilder)
11275                 return;
11276
11277         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11278         if (klass->parent != gklass->parent) {
11279                 MonoError error;
11280                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11281                 if (mono_error_ok (&error)) {
11282                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11283                         mono_metadata_free_type (parent_type);
11284                         if (parent != klass->parent) {
11285                                 /*fool mono_class_setup_parent*/
11286                                 klass->supertypes = NULL;
11287                                 mono_class_setup_parent (klass, parent);
11288                         }
11289                 } else {
11290                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11291                         mono_error_cleanup (&error);
11292                         if (gklass->wastypebuilder)
11293                                 klass->wastypebuilder = TRUE;
11294                         return;
11295                 }
11296         }
11297
11298         if (!dgclass->initialized)
11299                 return;
11300
11301         if (klass->method.count != gklass->method.count) {
11302                 klass->method.count = gklass->method.count;
11303                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11304
11305                 for (i = 0; i < klass->method.count; i++) {
11306                         MonoError error;
11307                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11308                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11309                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11310                 }
11311         }
11312
11313         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11314                 klass->interface_count = gklass->interface_count;
11315                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11316                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11317
11318                 for (i = 0; i < gklass->interface_count; ++i) {
11319                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11320                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11321                         mono_metadata_free_type (iface_type);
11322
11323                         ensure_runtime_vtable (klass->interfaces [i]);
11324                 }
11325                 klass->interfaces_inited = 1;
11326         }
11327
11328         if (klass->field.count != gklass->field.count) {
11329                 klass->field.count = gklass->field.count;
11330                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11331
11332                 for (i = 0; i < klass->field.count; i++) {
11333                         klass->fields [i] = gklass->fields [i];
11334                         klass->fields [i].parent = klass;
11335                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11336                 }
11337         }
11338
11339         /*We can only finish with this klass once it's parent has as well*/
11340         if (gklass->wastypebuilder)
11341                 klass->wastypebuilder = TRUE;
11342         return;
11343 }
11344
11345 static void
11346 ensure_generic_class_runtime_vtable (MonoClass *klass)
11347 {
11348         MonoClass *gklass = klass->generic_class->container_class;
11349
11350         ensure_runtime_vtable (gklass); 
11351
11352         fix_partial_generic_class (klass);
11353 }
11354
11355 static void
11356 ensure_runtime_vtable (MonoClass *klass)
11357 {
11358         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11359         int i, num, j;
11360
11361         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11362                 return;
11363         if (klass->parent)
11364                 ensure_runtime_vtable (klass->parent);
11365
11366         if (tb) {
11367                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11368                 num += tb->num_methods;
11369                 klass->method.count = num;
11370                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11371                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11372                 for (i = 0; i < num; ++i)
11373                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11374                 num = tb->num_methods;
11375                 j = i;
11376                 for (i = 0; i < num; ++i)
11377                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11378         
11379                 if (tb->interfaces) {
11380                         klass->interface_count = mono_array_length (tb->interfaces);
11381                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11382                         for (i = 0; i < klass->interface_count; ++i) {
11383                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11384                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11385                                 ensure_runtime_vtable (klass->interfaces [i]);
11386                         }
11387                         klass->interfaces_inited = 1;
11388                 }
11389         } else if (klass->generic_class){
11390                 ensure_generic_class_runtime_vtable (klass);
11391         }
11392
11393         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11394                 int slot_num = 0;
11395                 for (i = 0; i < klass->method.count; ++i) {
11396                         MonoMethod *im = klass->methods [i];
11397                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11398                                 im->slot = slot_num++;
11399                 }
11400                 
11401                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11402                 mono_class_setup_interface_offsets (klass);
11403                 mono_class_setup_interface_id (klass);
11404         }
11405
11406         /*
11407          * The generic vtable is needed even if image->run is not set since some
11408          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11409          * method->slot being defined.
11410          */
11411
11412         /* 
11413          * tb->methods could not be freed since it is used for determining 
11414          * overrides during dynamic vtable construction.
11415          */
11416 }
11417
11418 static MonoMethod*
11419 mono_reflection_method_get_handle (MonoObject *method)
11420 {
11421         MonoClass *klass = mono_object_class (method);
11422         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11423                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11424                 return sr_method->method;
11425         }
11426         if (is_sre_method_builder (klass)) {
11427                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11428                 return mb->mhandle;
11429         }
11430         if (is_sre_method_on_tb_inst (klass)) {
11431                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11432                 MonoMethod *result;
11433                 /*FIXME move this to a proper method and unify with resolve_object*/
11434                 if (m->method_args) {
11435                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11436                 } else {
11437                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11438                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11439                         MonoMethod *mono_method;
11440
11441                         if (is_sre_method_builder (mono_object_class (m->mb)))
11442                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11443                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11444                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11445                         else
11446                                 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)));
11447
11448                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11449                 }
11450                 return result;
11451         }
11452
11453         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11454         return NULL;
11455 }
11456
11457 void
11458 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11459 {
11460         MonoReflectionTypeBuilder *tb;
11461         int i, j, onum;
11462         MonoReflectionMethod *m;
11463
11464         *overrides = NULL;
11465         *num_overrides = 0;
11466
11467         g_assert (image_is_dynamic (klass->image));
11468
11469         if (!mono_class_get_ref_info (klass))
11470                 return;
11471
11472         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11473
11474         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11475
11476         onum = 0;
11477         if (tb->methods) {
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                                 onum += mono_array_length (mb->override_methods);
11483                 }
11484         }
11485
11486         if (onum) {
11487                 *overrides = g_new0 (MonoMethod*, onum * 2);
11488
11489                 onum = 0;
11490                 for (i = 0; i < tb->num_methods; ++i) {
11491                         MonoReflectionMethodBuilder *mb = 
11492                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11493                         if (mb->override_methods) {
11494                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11495                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11496
11497                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11498                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11499
11500                                         g_assert (mb->mhandle);
11501
11502                                         onum ++;
11503                                 }
11504                         }
11505                 }
11506         }
11507
11508         *num_overrides = onum;
11509 }
11510
11511 static void
11512 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11513 {
11514         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11515         MonoReflectionFieldBuilder *fb;
11516         MonoClassField *field;
11517         MonoImage *image = klass->image;
11518         const char *p, *p2;
11519         int i;
11520         guint32 len, idx, real_size = 0;
11521
11522         klass->field.count = tb->num_fields;
11523         klass->field.first = 0;
11524
11525         mono_error_init (error);
11526
11527         if (tb->class_size) {
11528                 if ((tb->packing_size & 0xffffff00) != 0) {
11529                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11530                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11531                         return;
11532                 }
11533                 klass->packing_size = tb->packing_size;
11534                 real_size = klass->instance_size + tb->class_size;
11535         }
11536
11537         if (!klass->field.count) {
11538                 klass->instance_size = MAX (klass->instance_size, real_size);
11539                 return;
11540         }
11541         
11542         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11543         mono_class_alloc_ext (klass);
11544         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11545         /*
11546         This is, guess what, a hack.
11547         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11548         On the static path no field class is resolved, only types are built. This is the right thing to do
11549         but we suck.
11550         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11551         */
11552         klass->size_inited = 1;
11553
11554         for (i = 0; i < klass->field.count; ++i) {
11555                 MonoArray *rva_data;
11556                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11557                 field = &klass->fields [i];
11558                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11559                 if (!mono_error_ok (error))
11560                         return;
11561                 if (fb->attrs) {
11562                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11563                         field->type->attrs = fb->attrs;
11564                 } else {
11565                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11566                 }
11567
11568                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11569                         char *base = mono_array_addr (rva_data, char, 0);
11570                         size_t size = mono_array_length (rva_data);
11571                         char *data = (char *)mono_image_alloc (klass->image, size);
11572                         memcpy (data, base, size);
11573                         klass->ext->field_def_values [i].data = data;
11574                 }
11575                 if (fb->offset != -1)
11576                         field->offset = fb->offset;
11577                 field->parent = klass;
11578                 fb->handle = field;
11579                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11580
11581                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11582                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11583                 }
11584                 if (fb->def_value) {
11585                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11586                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11587                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11588                         /* Copy the data from the blob since it might get realloc-ed */
11589                         p = assembly->blob.data + idx;
11590                         len = mono_metadata_decode_blob_size (p, &p2);
11591                         len += p2 - p;
11592                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
11593                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11594                 }
11595         }
11596
11597         klass->instance_size = MAX (klass->instance_size, real_size);
11598         mono_class_layout_fields (klass);
11599 }
11600
11601 static void
11602 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11603 {
11604         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11605         MonoReflectionPropertyBuilder *pb;
11606         MonoImage *image = klass->image;
11607         MonoProperty *properties;
11608         int i;
11609
11610         mono_error_init (error);
11611
11612         if (!klass->ext)
11613                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11614
11615         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11616         klass->ext->property.first = 0;
11617
11618         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11619         klass->ext->properties = properties;
11620         for (i = 0; i < klass->ext->property.count; ++i) {
11621                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11622                 properties [i].parent = klass;
11623                 properties [i].attrs = pb->attrs;
11624                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11625                 if (!mono_error_ok (error))
11626                         return;
11627                 if (pb->get_method)
11628                         properties [i].get = pb->get_method->mhandle;
11629                 if (pb->set_method)
11630                         properties [i].set = pb->set_method->mhandle;
11631
11632                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11633                 if (pb->def_value) {
11634                         guint32 len, idx;
11635                         const char *p, *p2;
11636                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11637                         if (!klass->ext->prop_def_values)
11638                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11639                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11640                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11641                         /* Copy the data from the blob since it might get realloc-ed */
11642                         p = assembly->blob.data + idx;
11643                         len = mono_metadata_decode_blob_size (p, &p2);
11644                         len += p2 - p;
11645                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
11646                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11647                 }
11648         }
11649 }
11650
11651 MonoReflectionEvent *
11652 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11653 {
11654         MonoEvent *event = g_new0 (MonoEvent, 1);
11655         MonoClass *klass;
11656
11657         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11658
11659         event->parent = klass;
11660         event->attrs = eb->attrs;
11661         event->name = mono_string_to_utf8 (eb->name);
11662         if (eb->add_method)
11663                 event->add = eb->add_method->mhandle;
11664         if (eb->remove_method)
11665                 event->remove = eb->remove_method->mhandle;
11666         if (eb->raise_method)
11667                 event->raise = eb->raise_method->mhandle;
11668
11669 #ifndef MONO_SMALL_CONFIG
11670         if (eb->other_methods) {
11671                 int j;
11672                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11673                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11674                         MonoReflectionMethodBuilder *mb = 
11675                                 mono_array_get (eb->other_methods,
11676                                                 MonoReflectionMethodBuilder*, j);
11677                         event->other [j] = mb->mhandle;
11678                 }
11679         }
11680 #endif
11681
11682         return mono_event_get_object (mono_object_domain (tb), klass, event);
11683 }
11684
11685 static void
11686 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11687 {
11688         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11689         MonoReflectionEventBuilder *eb;
11690         MonoImage *image = klass->image;
11691         MonoEvent *events;
11692         int i;
11693
11694         mono_error_init (error);
11695
11696         if (!klass->ext)
11697                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11698
11699         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11700         klass->ext->event.first = 0;
11701
11702         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11703         klass->ext->events = events;
11704         for (i = 0; i < klass->ext->event.count; ++i) {
11705                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11706                 events [i].parent = klass;
11707                 events [i].attrs = eb->attrs;
11708                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11709                 if (!mono_error_ok (error))
11710                         return;
11711                 if (eb->add_method)
11712                         events [i].add = eb->add_method->mhandle;
11713                 if (eb->remove_method)
11714                         events [i].remove = eb->remove_method->mhandle;
11715                 if (eb->raise_method)
11716                         events [i].raise = eb->raise_method->mhandle;
11717
11718 #ifndef MONO_SMALL_CONFIG
11719                 if (eb->other_methods) {
11720                         int j;
11721                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11722                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11723                                 MonoReflectionMethodBuilder *mb = 
11724                                         mono_array_get (eb->other_methods,
11725                                                                         MonoReflectionMethodBuilder*, j);
11726                                 events [i].other [j] = mb->mhandle;
11727                         }
11728                 }
11729 #endif
11730                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11731         }
11732 }
11733
11734 static gboolean
11735 remove_instantiations_of_and_ensure_contents (gpointer key,
11736                                                   gpointer value,
11737                                                   gpointer user_data)
11738 {
11739         MonoType *type = (MonoType*)key;
11740         MonoClass *klass = (MonoClass*)user_data;
11741
11742         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11743                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11744                 return TRUE;
11745         } else
11746                 return FALSE;
11747 }
11748
11749 static void
11750 check_array_for_usertypes (MonoArray *arr)
11751 {
11752         int i;
11753
11754         if (!arr)
11755                 return;
11756
11757         for (i = 0; i < mono_array_length (arr); ++i)
11758                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11759 }
11760
11761 MonoReflectionType*
11762 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11763 {
11764         MonoError error;
11765         MonoClass *klass;
11766         MonoDomain* domain;
11767         MonoReflectionType* res;
11768         int i, j;
11769
11770         domain = mono_object_domain (tb);
11771         klass = mono_class_from_mono_type (tb->type.type);
11772
11773         /*
11774          * Check for user defined Type subclasses.
11775          */
11776         RESOLVE_TYPE (tb->parent);
11777         check_array_for_usertypes (tb->interfaces);
11778         if (tb->fields) {
11779                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11780                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
11781                         if (fb) {
11782                                 RESOLVE_TYPE (fb->type);
11783                                 check_array_for_usertypes (fb->modreq);
11784                                 check_array_for_usertypes (fb->modopt);
11785                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11786                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11787                         }
11788                 }
11789         }
11790         if (tb->methods) {
11791                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11792                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
11793                         if (mb) {
11794                                 RESOLVE_TYPE (mb->rtype);
11795                                 check_array_for_usertypes (mb->return_modreq);
11796                                 check_array_for_usertypes (mb->return_modopt);
11797                                 check_array_for_usertypes (mb->parameters);
11798                                 if (mb->param_modreq)
11799                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11800                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11801                                 if (mb->param_modopt)
11802                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11803                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11804                         }
11805                 }
11806         }
11807         if (tb->ctors) {
11808                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11809                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
11810                         if (mb) {
11811                                 check_array_for_usertypes (mb->parameters);
11812                                 if (mb->param_modreq)
11813                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11814                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11815                                 if (mb->param_modopt)
11816                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11817                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11818                         }
11819                 }
11820         }
11821
11822         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11823
11824         /* 
11825          * we need to lock the domain because the lock will be taken inside
11826          * So, we need to keep the locking order correct.
11827          */
11828         mono_loader_lock ();
11829         mono_domain_lock (domain);
11830         if (klass->wastypebuilder) {
11831                 mono_domain_unlock (domain);
11832                 mono_loader_unlock ();
11833                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11834         }
11835         /*
11836          * Fields to set in klass:
11837          * the various flags: delegate/unicode/contextbound etc.
11838          */
11839         klass->flags = tb->attrs;
11840         klass->has_cctor = 1;
11841         klass->has_finalize = 1;
11842         klass->has_finalize_inited = 1;
11843
11844         mono_class_setup_parent (klass, klass->parent);
11845         /* fool mono_class_setup_supertypes */
11846         klass->supertypes = NULL;
11847         mono_class_setup_supertypes (klass);
11848         mono_class_setup_mono_type (klass);
11849
11850 #if 0
11851         if (!((MonoDynamicImage*)klass->image)->run) {
11852                 if (klass->generic_container) {
11853                         /* FIXME: The code below can't handle generic classes */
11854                         klass->wastypebuilder = TRUE;
11855                         mono_loader_unlock ();
11856                         mono_domain_unlock (domain);
11857                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11858                 }
11859         }
11860 #endif
11861
11862         /* enums are done right away */
11863         if (!klass->enumtype)
11864                 ensure_runtime_vtable (klass);
11865
11866         if (tb->subtypes) {
11867                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11868                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11869                         mono_class_alloc_ext (klass);
11870                         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)));
11871                 }
11872         }
11873
11874         klass->nested_classes_inited = TRUE;
11875
11876         /* fields and object layout */
11877         if (klass->parent) {
11878                 if (!klass->parent->size_inited)
11879                         mono_class_init (klass->parent);
11880                 klass->instance_size = klass->parent->instance_size;
11881                 klass->sizes.class_size = 0;
11882                 klass->min_align = klass->parent->min_align;
11883                 /* if the type has no fields we won't call the field_setup
11884                  * routine which sets up klass->has_references.
11885                  */
11886                 klass->has_references |= klass->parent->has_references;
11887         } else {
11888                 klass->instance_size = sizeof (MonoObject);
11889                 klass->min_align = 1;
11890         }
11891
11892         /* FIXME: handle packing_size and instance_size */
11893         typebuilder_setup_fields (klass, &error);
11894         if (!mono_error_ok (&error))
11895                 goto failure;
11896         typebuilder_setup_properties (klass, &error);
11897         if (!mono_error_ok (&error))
11898                 goto failure;
11899
11900         typebuilder_setup_events (klass, &error);
11901         if (!mono_error_ok (&error))
11902                 goto failure;
11903
11904         klass->wastypebuilder = TRUE;
11905
11906         /* 
11907          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11908          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11909          * we want to return normal System.MonoType objects, so clear these out from the cache.
11910          *
11911          * Together with this we must ensure the contents of all instances to match the created type.
11912          */
11913         if (domain->type_hash && klass->generic_container)
11914                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11915
11916         mono_domain_unlock (domain);
11917         mono_loader_unlock ();
11918
11919         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11920                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11921                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11922         }
11923
11924         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11925         g_assert (res != (MonoReflectionType*)tb);
11926
11927         return res;
11928
11929 failure:
11930         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11931         klass->wastypebuilder = TRUE;
11932         mono_domain_unlock (domain);
11933         mono_loader_unlock ();
11934         mono_error_raise_exception (&error);
11935         return NULL;
11936 }
11937
11938 void
11939 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11940 {
11941         MonoGenericParamFull *param;
11942         MonoImage *image;
11943         MonoClass *pklass;
11944         MonoError error;
11945
11946         image = &gparam->tbuilder->module->dynamic_image->image;
11947
11948         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11949
11950         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11951         g_assert (mono_error_ok (&error));
11952         param->param.num = gparam->index;
11953
11954         if (gparam->mbuilder) {
11955                 if (!gparam->mbuilder->generic_container) {
11956                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11957                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11958                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11959                         gparam->mbuilder->generic_container->is_method = TRUE;
11960                         /* 
11961                          * Cannot set owner.method, since the MonoMethod is not created yet.
11962                          * Set the image field instead, so type_in_image () works.
11963                          */
11964                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
11965                         gparam->mbuilder->generic_container->owner.image = klass->image;
11966                 }
11967                 param->param.owner = gparam->mbuilder->generic_container;
11968         } else if (gparam->tbuilder) {
11969                 if (!gparam->tbuilder->generic_container) {
11970                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11971                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11972                         gparam->tbuilder->generic_container->owner.klass = klass;
11973                 }
11974                 param->param.owner = gparam->tbuilder->generic_container;
11975         }
11976
11977         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
11978
11979         gparam->type.type = &pklass->byval_arg;
11980
11981         mono_class_set_ref_info (pklass, gparam);
11982         mono_image_append_class_to_reflection_info_set (pklass);
11983 }
11984
11985 MonoArray *
11986 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11987 {
11988         MonoReflectionModuleBuilder *module = sig->module;
11989         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11990         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11991         guint32 buflen, i;
11992         MonoArray *result;
11993         SigBuffer buf;
11994
11995         check_array_for_usertypes (sig->arguments);
11996
11997         sigbuffer_init (&buf, 32);
11998
11999         sigbuffer_add_value (&buf, 0x07);
12000         sigbuffer_add_value (&buf, na);
12001         if (assembly != NULL){
12002                 for (i = 0; i < na; ++i) {
12003                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12004                         encode_reflection_type (assembly, type, &buf);
12005                 }
12006         }
12007
12008         buflen = buf.p - buf.buf;
12009         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12010         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12011         sigbuffer_free (&buf);
12012
12013         return result;
12014 }
12015
12016 MonoArray *
12017 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12018 {
12019         MonoDynamicImage *assembly = sig->module->dynamic_image;
12020         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12021         guint32 buflen, i;
12022         MonoArray *result;
12023         SigBuffer buf;
12024
12025         check_array_for_usertypes (sig->arguments);
12026
12027         sigbuffer_init (&buf, 32);
12028
12029         sigbuffer_add_value (&buf, 0x06);
12030         for (i = 0; i < na; ++i) {
12031                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12032                 encode_reflection_type (assembly, type, &buf);
12033         }
12034
12035         buflen = buf.p - buf.buf;
12036         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12037         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12038         sigbuffer_free (&buf);
12039
12040         return result;
12041 }
12042
12043 typedef struct {
12044         MonoMethod *handle;
12045         MonoDomain *domain;
12046 } DynamicMethodReleaseData;
12047
12048 /*
12049  * The runtime automatically clean up those after finalization.
12050 */      
12051 static MonoReferenceQueue *dynamic_method_queue;
12052
12053 static void
12054 free_dynamic_method (void *dynamic_method)
12055 {
12056         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12057         MonoDomain *domain = data->domain;
12058         MonoMethod *method = data->handle;
12059         guint32 dis_link;
12060
12061         mono_domain_lock (domain);
12062         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12063         g_hash_table_remove (domain->method_to_dyn_method, method);
12064         mono_domain_unlock (domain);
12065         g_assert (dis_link);
12066         mono_gchandle_free (dis_link);
12067
12068         mono_runtime_free_method (domain, method);
12069         g_free (data);
12070 }
12071
12072 void 
12073 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12074 {
12075         MonoReferenceQueue *queue;
12076         MonoMethod *handle;
12077         DynamicMethodReleaseData *release_data;
12078         ReflectionMethodBuilder rmb;
12079         MonoMethodSignature *sig;
12080         MonoClass *klass;
12081         MonoDomain *domain;
12082         GSList *l;
12083         int i;
12084
12085         if (mono_runtime_is_shutting_down ())
12086                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12087
12088         if (!(queue = dynamic_method_queue)) {
12089                 mono_loader_lock ();
12090                 if (!(queue = dynamic_method_queue))
12091                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12092                 mono_loader_unlock ();
12093         }
12094
12095         sig = dynamic_method_to_signature (mb);
12096
12097         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12098
12099         /*
12100          * Resolve references.
12101          */
12102         /* 
12103          * Every second entry in the refs array is reserved for storing handle_class,
12104          * which is needed by the ldtoken implementation in the JIT.
12105          */
12106         rmb.nrefs = mb->nrefs;
12107         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12108         for (i = 0; i < mb->nrefs; i += 2) {
12109                 MonoClass *handle_class;
12110                 gpointer ref;
12111                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12112
12113                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12114                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12115                         /*
12116                          * The referenced DynamicMethod should already be created by the managed
12117                          * code, except in the case of circular references. In that case, we store
12118                          * method in the refs array, and fix it up later when the referenced 
12119                          * DynamicMethod is created.
12120                          */
12121                         if (method->mhandle) {
12122                                 ref = method->mhandle;
12123                         } else {
12124                                 /* FIXME: GC object stored in unmanaged memory */
12125                                 ref = method;
12126
12127                                 /* FIXME: GC object stored in unmanaged memory */
12128                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12129                         }
12130                         handle_class = mono_defaults.methodhandle_class;
12131                 } else {
12132                         MonoException *ex = NULL;
12133                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12134                         if (!ref)
12135                                 ex = mono_get_exception_type_load (NULL, NULL);
12136                         else if (mono_security_core_clr_enabled ())
12137                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12138
12139                         if (ex) {
12140                                 g_free (rmb.refs);
12141                                 mono_raise_exception (ex);
12142                                 return;
12143                         }
12144                 }
12145
12146                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12147                 rmb.refs [i + 1] = handle_class;
12148         }               
12149
12150         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12151
12152         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12153         release_data = g_new (DynamicMethodReleaseData, 1);
12154         release_data->handle = handle;
12155         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12156         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12157                 g_free (release_data);
12158
12159         /* Fix up refs entries pointing at us */
12160         for (l = mb->referenced_by; l; l = l->next) {
12161                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12162                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12163                 gpointer *data;
12164                 
12165                 g_assert (method->mhandle);
12166
12167                 data = (gpointer*)wrapper->method_data;
12168                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12169                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12170                                 data [i + 1] = mb->mhandle;
12171                 }
12172         }
12173         g_slist_free (mb->referenced_by);
12174
12175         g_free (rmb.refs);
12176
12177         /* ilgen is no longer needed */
12178         mb->ilgen = NULL;
12179
12180         domain = mono_domain_get ();
12181         mono_domain_lock (domain);
12182         if (!domain->method_to_dyn_method)
12183                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12184         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12185         mono_domain_unlock (domain);
12186 }
12187
12188 #endif /* DISABLE_REFLECTION_EMIT */
12189
12190 /**
12191  * 
12192  * mono_reflection_is_valid_dynamic_token:
12193  * 
12194  * Returns TRUE if token is valid.
12195  * 
12196  */
12197 gboolean
12198 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12199 {
12200         return lookup_dyn_token (image, token) != NULL;
12201 }
12202
12203 MonoMethodSignature *
12204 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12205 {
12206         MonoMethodSignature *sig;
12207         g_assert (image_is_dynamic (image));
12208
12209         mono_error_init (error);
12210
12211         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12212         if (sig)
12213                 return sig;
12214
12215         return mono_method_signature_checked (method, error);
12216 }
12217
12218 #ifndef DISABLE_REFLECTION_EMIT
12219
12220 /**
12221  * mono_reflection_lookup_dynamic_token:
12222  *
12223  * Finish the Builder object pointed to by TOKEN and return the corresponding
12224  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12225  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12226  * mapping table.
12227  *
12228  * LOCKING: Take the loader lock
12229  */
12230 gpointer
12231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12232 {
12233         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12234         MonoObject *obj;
12235         MonoClass *klass;
12236
12237         obj = lookup_dyn_token (assembly, token);
12238         if (!obj) {
12239                 if (valid_token)
12240                         g_error ("Could not find required dynamic token 0x%08x", token);
12241                 else
12242                         return NULL;
12243         }
12244
12245         if (!handle_class)
12246                 handle_class = &klass;
12247         return resolve_object (image, obj, handle_class, context);
12248 }
12249
12250 /*
12251  * ensure_complete_type:
12252  *
12253  *   Ensure that KLASS is completed if it is a dynamic type, or references
12254  * dynamic types.
12255  */
12256 static void
12257 ensure_complete_type (MonoClass *klass)
12258 {
12259         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12260                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12261
12262                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12263
12264                 // Asserting here could break a lot of code
12265                 //g_assert (klass->wastypebuilder);
12266         }
12267
12268         if (klass->generic_class) {
12269                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12270                 int i;
12271
12272                 for (i = 0; i < inst->type_argc; ++i) {
12273                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12274                 }
12275         }
12276 }
12277
12278 static gpointer
12279 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12280 {
12281         gpointer result = NULL;
12282
12283         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12284                 result = mono_string_intern ((MonoString*)obj);
12285                 *handle_class = mono_defaults.string_class;
12286                 g_assert (result);
12287         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12288                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12289                 MonoClass *mc = mono_class_from_mono_type (type);
12290                 if (!mono_class_init (mc))
12291                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12292
12293                 if (context) {
12294                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12295                         result = mono_class_from_mono_type (inflated);
12296                         mono_metadata_free_type (inflated);
12297                 } else {
12298                         result = mono_class_from_mono_type (type);
12299                 }
12300                 *handle_class = mono_defaults.typehandle_class;
12301                 g_assert (result);
12302         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12303                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12304                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12305                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12306                 result = ((MonoReflectionMethod*)obj)->method;
12307                 if (context) {
12308                         MonoError error;
12309                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12310                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12311                 }
12312                 *handle_class = mono_defaults.methodhandle_class;
12313                 g_assert (result);
12314         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12315                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12316                 result = mb->mhandle;
12317                 if (!result) {
12318                         /* Type is not yet created */
12319                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12320
12321                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12322
12323                         /*
12324                          * Hopefully this has been filled in by calling CreateType() on the
12325                          * TypeBuilder.
12326                          */
12327                         /*
12328                          * TODO: This won't work if the application finishes another 
12329                          * TypeBuilder instance instead of this one.
12330                          */
12331                         result = mb->mhandle;
12332                 }
12333                 if (context) {
12334                         MonoError error;
12335                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12336                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12337                 }
12338                 *handle_class = mono_defaults.methodhandle_class;
12339         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12340                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12341
12342                 result = cb->mhandle;
12343                 if (!result) {
12344                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12345
12346                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12347                         result = cb->mhandle;
12348                 }
12349                 if (context) {
12350                         MonoError error;
12351                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12352                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12353                 }
12354                 *handle_class = mono_defaults.methodhandle_class;
12355         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12356                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12357
12358                 ensure_complete_type (field->parent);
12359                 if (context) {
12360                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12361                         MonoClass *klass = mono_class_from_mono_type (inflated);
12362                         MonoClassField *inflated_field;
12363                         gpointer iter = NULL;
12364                         mono_metadata_free_type (inflated);
12365                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12366                                 if (!strcmp (field->name, inflated_field->name))
12367                                         break;
12368                         }
12369                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12370                         result = inflated_field;
12371                 } else {
12372                         result = field;
12373                 }
12374                 *handle_class = mono_defaults.fieldhandle_class;
12375                 g_assert (result);
12376         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12377                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12378                 result = fb->handle;
12379
12380                 if (!result) {
12381                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12382
12383                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12384                         result = fb->handle;
12385                 }
12386
12387                 if (fb->handle && fb->handle->parent->generic_container) {
12388                         MonoClass *klass = fb->handle->parent;
12389                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12390                         MonoClass *inflated = mono_class_from_mono_type (type);
12391
12392                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12393                         g_assert (result);
12394                         mono_metadata_free_type (type);
12395                 }
12396                 *handle_class = mono_defaults.fieldhandle_class;
12397         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12398                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12399                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12400                 MonoClass *klass;
12401
12402                 klass = type->data.klass;
12403                 if (klass->wastypebuilder) {
12404                         /* Already created */
12405                         result = klass;
12406                 }
12407                 else {
12408                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12409                         result = type->data.klass;
12410                         g_assert (result);
12411                 }
12412                 *handle_class = mono_defaults.typehandle_class;
12413         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12414                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12415                 MonoMethodSignature *sig;
12416                 int nargs, i;
12417
12418                 if (helper->arguments)
12419                         nargs = mono_array_length (helper->arguments);
12420                 else
12421                         nargs = 0;
12422
12423                 sig = mono_metadata_signature_alloc (image, nargs);
12424                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12425                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12426
12427                 if (helper->unmanaged_call_conv) { /* unmanaged */
12428                         sig->call_convention = helper->unmanaged_call_conv - 1;
12429                         sig->pinvoke = TRUE;
12430                 } else if (helper->call_conv & 0x02) {
12431                         sig->call_convention = MONO_CALL_VARARG;
12432                 } else {
12433                         sig->call_convention = MONO_CALL_DEFAULT;
12434                 }
12435
12436                 sig->param_count = nargs;
12437                 /* TODO: Copy type ? */
12438                 sig->ret = helper->return_type->type;
12439                 for (i = 0; i < nargs; ++i)
12440                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12441
12442                 result = sig;
12443                 *handle_class = NULL;
12444         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12445                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12446                 /* Already created by the managed code */
12447                 g_assert (method->mhandle);
12448                 result = method->mhandle;
12449                 *handle_class = mono_defaults.methodhandle_class;
12450         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12451                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12452                 type = mono_class_inflate_generic_type (type, context);
12453                 result = mono_class_from_mono_type (type);
12454                 *handle_class = mono_defaults.typehandle_class;
12455                 g_assert (result);
12456                 mono_metadata_free_type (type);
12457         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12458                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12459                 type = mono_class_inflate_generic_type (type, context);
12460                 result = mono_class_from_mono_type (type);
12461                 *handle_class = mono_defaults.typehandle_class;
12462                 g_assert (result);
12463                 mono_metadata_free_type (type);
12464         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12465                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12466                 MonoClass *inflated;
12467                 MonoType *type;
12468                 MonoClassField *field;
12469
12470                 if (is_sre_field_builder (mono_object_class (f->fb)))
12471                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12472                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12473                         field = ((MonoReflectionField*)f->fb)->field;
12474                 else
12475                         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)));
12476
12477                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12478                 inflated = mono_class_from_mono_type (type);
12479
12480                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12481                 ensure_complete_type (field->parent);
12482                 g_assert (result);
12483                 mono_metadata_free_type (type);
12484                 *handle_class = mono_defaults.fieldhandle_class;
12485         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12486                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12487                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12488                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12489                 MonoMethod *method;
12490
12491                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12492                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12493                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12494                         method = ((MonoReflectionMethod *)c->cb)->method;
12495                 else
12496                         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)));
12497
12498                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12499                 *handle_class = mono_defaults.methodhandle_class;
12500                 mono_metadata_free_type (type);
12501         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12502                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12503                 if (m->method_args) {
12504                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12505                         if (context) {
12506                                 MonoError error;
12507                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12508                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12509                         }
12510                 } else {
12511                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12512                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12513                         MonoMethod *method;
12514
12515                         if (is_sre_method_builder (mono_object_class (m->mb)))
12516                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12517                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12518                                 method = ((MonoReflectionMethod *)m->mb)->method;
12519                         else
12520                                 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)));
12521
12522                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12523                         mono_metadata_free_type (type);
12524                 }
12525                 *handle_class = mono_defaults.methodhandle_class;
12526         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12527                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12528                 MonoType *mtype;
12529                 MonoClass *klass;
12530                 MonoMethod *method;
12531                 gpointer iter;
12532                 char *name;
12533
12534                 mtype = mono_reflection_type_get_handle (m->parent);
12535                 klass = mono_class_from_mono_type (mtype);
12536
12537                 /* Find the method */
12538
12539                 name = mono_string_to_utf8 (m->name);
12540                 iter = NULL;
12541                 while ((method = mono_class_get_methods (klass, &iter))) {
12542                         if (!strcmp (method->name, name))
12543                                 break;
12544                 }
12545                 g_free (name);
12546
12547                 // FIXME:
12548                 g_assert (method);
12549                 // FIXME: Check parameters/return value etc. match
12550
12551                 result = method;
12552                 *handle_class = mono_defaults.methodhandle_class;
12553         } else if (is_sre_array (mono_object_get_class(obj)) ||
12554                                 is_sre_byref (mono_object_get_class(obj)) ||
12555                                 is_sre_pointer (mono_object_get_class(obj))) {
12556                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12557                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12558
12559                 if (context) {
12560                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12561                         result = mono_class_from_mono_type (inflated);
12562                         mono_metadata_free_type (inflated);
12563                 } else {
12564                         result = mono_class_from_mono_type (type);
12565                 }
12566                 *handle_class = mono_defaults.typehandle_class;
12567         } else {
12568                 g_print ("%s\n", obj->vtable->klass->name);
12569                 g_assert_not_reached ();
12570         }
12571         return result;
12572 }
12573
12574 #else /* DISABLE_REFLECTION_EMIT */
12575
12576 MonoArray*
12577 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12578 {
12579         g_assert_not_reached ();
12580         return NULL;
12581 }
12582
12583 void
12584 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12585 {
12586         g_assert_not_reached ();
12587 }
12588
12589 void
12590 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12591 {
12592         g_assert_not_reached ();
12593 }
12594
12595 void
12596 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12597 {
12598         g_assert_not_reached ();
12599 }
12600
12601 void
12602 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12603 {
12604         g_assert_not_reached ();
12605 }
12606
12607 void
12608 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12609 {
12610         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12611 }
12612
12613 void
12614 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12615 {
12616         g_assert_not_reached ();
12617 }
12618
12619 void
12620 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12621 {
12622         g_assert_not_reached ();
12623 }
12624
12625 MonoReflectionModule *
12626 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12627 {
12628         g_assert_not_reached ();
12629         return NULL;
12630 }
12631
12632 guint32
12633 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12634 {
12635         g_assert_not_reached ();
12636         return 0;
12637 }
12638
12639 guint32
12640 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12641 {
12642         g_assert_not_reached ();
12643         return 0;
12644 }
12645
12646 guint32
12647 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12648                                                  gboolean create_open_instance, gboolean register_token)
12649 {
12650         g_assert_not_reached ();
12651         return 0;
12652 }
12653
12654 void
12655 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12656 {
12657 }
12658
12659 void
12660 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12661 {
12662         g_assert_not_reached ();
12663 }
12664
12665 void
12666 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12667 {
12668         *overrides = NULL;
12669         *num_overrides = 0;
12670 }
12671
12672 MonoReflectionEvent *
12673 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12674 {
12675         g_assert_not_reached ();
12676         return NULL;
12677 }
12678
12679 MonoReflectionType*
12680 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12681 {
12682         g_assert_not_reached ();
12683         return NULL;
12684 }
12685
12686 void
12687 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12688 {
12689         g_assert_not_reached ();
12690 }
12691
12692 MonoArray *
12693 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12694 {
12695         g_assert_not_reached ();
12696         return NULL;
12697 }
12698
12699 MonoArray *
12700 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12701 {
12702         g_assert_not_reached ();
12703         return NULL;
12704 }
12705
12706 void 
12707 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12708 {
12709 }
12710
12711 gpointer
12712 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12713 {
12714         return NULL;
12715 }
12716
12717 MonoType*
12718 mono_reflection_type_get_handle (MonoReflectionType* ref)
12719 {
12720         if (!ref)
12721                 return NULL;
12722         return ref->type;
12723 }
12724
12725 void
12726 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12727 {
12728         g_assert_not_reached ();
12729 }
12730
12731 #endif /* DISABLE_REFLECTION_EMIT */
12732
12733 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12734 const static guint32 declsec_flags_map[] = {
12735         0x00000000,                                     /* empty */
12736         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12737         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12738         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12739         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12740         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12741         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12742         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12743         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12744         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12745         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12746         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12747         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12748         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12749         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12750         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12751         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12752         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12753         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12754 };
12755
12756 /*
12757  * Returns flags that includes all available security action associated to the handle.
12758  * @token: metadata token (either for a class or a method)
12759  * @image: image where resides the metadata.
12760  */
12761 static guint32
12762 mono_declsec_get_flags (MonoImage *image, guint32 token)
12763 {
12764         int index = mono_metadata_declsec_from_index (image, token);
12765         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12766         guint32 result = 0;
12767         guint32 action;
12768         int i;
12769
12770         /* HasSecurity can be present for other, not specially encoded, attributes,
12771            e.g. SuppressUnmanagedCodeSecurityAttribute */
12772         if (index < 0)
12773                 return 0;
12774
12775         for (i = index; i < t->rows; i++) {
12776                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12777
12778                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12779                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12780                         break;
12781
12782                 action = cols [MONO_DECL_SECURITY_ACTION];
12783                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12784                         result |= declsec_flags_map [action];
12785                 } else {
12786                         g_assert_not_reached ();
12787                 }
12788         }
12789         return result;
12790 }
12791
12792 /*
12793  * Get the security actions (in the form of flags) associated with the specified method.
12794  *
12795  * @method: The method for which we want the declarative security flags.
12796  * Return the declarative security flags for the method (only).
12797  *
12798  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12799  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12800  */
12801 guint32
12802 mono_declsec_flags_from_method (MonoMethod *method)
12803 {
12804         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12805                 /* FIXME: No cache (for the moment) */
12806                 guint32 idx = mono_method_get_index (method);
12807                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12808                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12809                 return mono_declsec_get_flags (method->klass->image, idx);
12810         }
12811         return 0;
12812 }
12813
12814 /*
12815  * Get the security actions (in the form of flags) associated with the specified class.
12816  *
12817  * @klass: The class for which we want the declarative security flags.
12818  * Return the declarative security flags for the class.
12819  *
12820  * Note: We cache the flags inside the MonoClass structure as this will get 
12821  *       called very often (at least for each method).
12822  */
12823 guint32
12824 mono_declsec_flags_from_class (MonoClass *klass)
12825 {
12826         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12827                 if (!klass->ext || !klass->ext->declsec_flags) {
12828                         guint32 idx;
12829
12830                         idx = mono_metadata_token_index (klass->type_token);
12831                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12832                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12833                         mono_loader_lock ();
12834                         mono_class_alloc_ext (klass);
12835                         mono_loader_unlock ();
12836                         /* we cache the flags on classes */
12837                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12838                 }
12839                 return klass->ext->declsec_flags;
12840         }
12841         return 0;
12842 }
12843
12844 /*
12845  * Get the security actions (in the form of flags) associated with the specified assembly.
12846  *
12847  * @assembly: The assembly for which we want the declarative security flags.
12848  * Return the declarative security flags for the assembly.
12849  */
12850 guint32
12851 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12852 {
12853         guint32 idx = 1; /* there is only one assembly */
12854         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12855         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12856         return mono_declsec_get_flags (assembly->image, idx);
12857 }
12858
12859
12860 /*
12861  * Fill actions for the specific index (which may either be an encoded class token or
12862  * an encoded method token) from the metadata image.
12863  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12864  */
12865 static MonoBoolean
12866 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12867         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12868 {
12869         MonoBoolean result = FALSE;
12870         MonoTableInfo *t;
12871         guint32 cols [MONO_DECL_SECURITY_SIZE];
12872         int index = mono_metadata_declsec_from_index (image, token);
12873         int i;
12874
12875         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12876         for (i = index; i < t->rows; i++) {
12877                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12878
12879                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12880                         return result;
12881
12882                 /* if present only replace (class) permissions with method permissions */
12883                 /* if empty accept either class or method permissions */
12884                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12885                         if (!actions->demand.blob) {
12886                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12887                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12888                                 actions->demand.blob = (char*) (blob + 2);
12889                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12890                                 result = TRUE;
12891                         }
12892                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12893                         if (!actions->noncasdemand.blob) {
12894                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12895                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12896                                 actions->noncasdemand.blob = (char*) (blob + 2);
12897                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12898                                 result = TRUE;
12899                         }
12900                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12901                         if (!actions->demandchoice.blob) {
12902                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12903                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12904                                 actions->demandchoice.blob = (char*) (blob + 2);
12905                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12906                                 result = TRUE;
12907                         }
12908                 }
12909         }
12910
12911         return result;
12912 }
12913
12914 static MonoBoolean
12915 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12916         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12917 {
12918         guint32 idx = mono_metadata_token_index (klass->type_token);
12919         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12920         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12921         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12922 }
12923
12924 static MonoBoolean
12925 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12926         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12927 {
12928         guint32 idx = mono_method_get_index (method);
12929         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12930         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12931         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12932 }
12933
12934 /*
12935  * Collect all actions (that requires to generate code in mini) assigned for
12936  * the specified method.
12937  * Note: Don't use the content of actions if the function return FALSE.
12938  */
12939 MonoBoolean
12940 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12941 {
12942         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12943                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12944         MonoBoolean result = FALSE;
12945         guint32 flags;
12946
12947         /* quick exit if no declarative security is present in the metadata */
12948         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12949                 return FALSE;
12950
12951         /* we want the original as the wrapper is "free" of the security informations */
12952         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12953                 method = mono_marshal_method_from_wrapper (method);
12954                 if (!method)
12955                         return FALSE;
12956         }
12957
12958         /* First we look for method-level attributes */
12959         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12960                 mono_class_init (method->klass);
12961                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12962
12963                 result = mono_declsec_get_method_demands_params (method, demands, 
12964                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12965         }
12966
12967         /* Here we use (or create) the class declarative cache to look for demands */
12968         flags = mono_declsec_flags_from_class (method->klass);
12969         if (flags & mask) {
12970                 if (!result) {
12971                         mono_class_init (method->klass);
12972                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12973                 }
12974                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12975                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12976         }
12977
12978         /* The boolean return value is used as a shortcut in case nothing needs to
12979            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12980         return result;
12981 }
12982
12983
12984 /*
12985  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12986  *
12987  * Note: Don't use the content of actions if the function return FALSE.
12988  */
12989 MonoBoolean
12990 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12991 {
12992         MonoBoolean result = FALSE;
12993         guint32 flags;
12994
12995         /* quick exit if no declarative security is present in the metadata */
12996         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12997                 return FALSE;
12998
12999         /* we want the original as the wrapper is "free" of the security informations */
13000         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13001                 method = mono_marshal_method_from_wrapper (method);
13002                 if (!method)
13003                         return FALSE;
13004         }
13005
13006         /* results are independant - zeroize both */
13007         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13008         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13009
13010         /* First we look for method-level attributes */
13011         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13012                 mono_class_init (method->klass);
13013
13014                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13015                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13016         }
13017
13018         /* Here we use (or create) the class declarative cache to look for demands */
13019         flags = mono_declsec_flags_from_class (method->klass);
13020         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13021                 mono_class_init (method->klass);
13022
13023                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13024                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13025         }
13026
13027         return result;
13028 }
13029
13030 /*
13031  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13032  *
13033  * @klass       The inherited class - this is the class that provides the security check (attributes)
13034  * @demans      
13035  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13036  * 
13037  * Note: Don't use the content of actions if the function return FALSE.
13038  */
13039 MonoBoolean
13040 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13041 {
13042         MonoBoolean result = FALSE;
13043         guint32 flags;
13044
13045         /* quick exit if no declarative security is present in the metadata */
13046         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13047                 return FALSE;
13048
13049         /* Here we use (or create) the class declarative cache to look for demands */
13050         flags = mono_declsec_flags_from_class (klass);
13051         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13052                 mono_class_init (klass);
13053                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13054
13055                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13056                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13057         }
13058
13059         return result;
13060 }
13061
13062 /*
13063  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13064  *
13065  * Note: Don't use the content of actions if the function return FALSE.
13066  */
13067 MonoBoolean
13068 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13069 {
13070         /* quick exit if no declarative security is present in the metadata */
13071         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13072                 return FALSE;
13073
13074         /* we want the original as the wrapper is "free" of the security informations */
13075         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13076                 method = mono_marshal_method_from_wrapper (method);
13077                 if (!method)
13078                         return FALSE;
13079         }
13080
13081         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13082                 mono_class_init (method->klass);
13083                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13084
13085                 return mono_declsec_get_method_demands_params (method, demands, 
13086                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13087         }
13088         return FALSE;
13089 }
13090
13091
13092 static MonoBoolean
13093 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13094 {
13095         guint32 cols [MONO_DECL_SECURITY_SIZE];
13096         MonoTableInfo *t;
13097         int i;
13098
13099         int index = mono_metadata_declsec_from_index (image, token);
13100         if (index == -1)
13101                 return FALSE;
13102
13103         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13104         for (i = index; i < t->rows; i++) {
13105                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13106
13107                 /* shortcut - index are ordered */
13108                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13109                         return FALSE;
13110
13111                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13112                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13113                         entry->blob = (char*) (metadata + 2);
13114                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13115                         return TRUE;
13116                 }
13117         }
13118
13119         return FALSE;
13120 }
13121
13122 MonoBoolean
13123 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13124 {
13125         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13126                 guint32 idx = mono_method_get_index (method);
13127                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13128                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13129                 return get_declsec_action (method->klass->image, idx, action, entry);
13130         }
13131         return FALSE;
13132 }
13133
13134 MonoBoolean
13135 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13136 {
13137         /* use cache */
13138         guint32 flags = mono_declsec_flags_from_class (klass);
13139         if (declsec_flags_map [action] & flags) {
13140                 guint32 idx = mono_metadata_token_index (klass->type_token);
13141                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13142                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13143                 return get_declsec_action (klass->image, idx, action, entry);
13144         }
13145         return FALSE;
13146 }
13147
13148 MonoBoolean
13149 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13150 {
13151         guint32 idx = 1; /* there is only one assembly */
13152         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13153         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13154
13155         return get_declsec_action (assembly->image, idx, action, entry);
13156 }
13157
13158 gboolean
13159 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13160 {
13161         MonoObject *res, *exc;
13162         void *params [1];
13163         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13164         static MonoMethod *method = NULL;
13165
13166         if (!System_Reflection_Emit_TypeBuilder) {
13167                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13168                 g_assert (System_Reflection_Emit_TypeBuilder);
13169         }
13170         if (method == NULL) {
13171                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13172                 g_assert (method);
13173         }
13174
13175         /* 
13176          * The result of mono_type_get_object () might be a System.MonoType but we
13177          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13178          */
13179         g_assert (mono_class_get_ref_info (klass));
13180         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13181
13182         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13183
13184         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13185         if (exc)
13186                 return FALSE;
13187         else
13188                 return *(MonoBoolean*)mono_object_unbox (res);
13189 }
13190
13191 /**
13192  * mono_reflection_type_get_type:
13193  * @reftype: the System.Type object
13194  *
13195  * Returns the MonoType* associated with the C# System.Type object @reftype.
13196  */
13197 MonoType*
13198 mono_reflection_type_get_type (MonoReflectionType *reftype)
13199 {
13200         g_assert (reftype);
13201
13202         return mono_reflection_type_get_handle (reftype);
13203 }
13204
13205 /**
13206  * mono_reflection_assembly_get_assembly:
13207  * @refassembly: the System.Reflection.Assembly object
13208  *
13209  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13210  */
13211 MonoAssembly*
13212 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13213 {
13214         g_assert (refassembly);
13215
13216         return refassembly->assembly;
13217 }
13218