Merge pull request #2223 from lobrien/master
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void    ensure_runtime_vtable (MonoClass *klass);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
198 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
199         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
200         __type = mono_reflection_type_resolve_user_types (__type);      \
201         mono_array_set (arr, MonoReflectionType*, index, __type);       \
202 } while (0)
203
204 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205
206 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
207 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
208
209 #if SIZEOF_VOID_P == 4
210 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
211 #else
212 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
213 #endif
214
215 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
216 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
217
218
219 void
220 mono_reflection_init (void)
221 {
222 }
223
224 static inline void
225 dynamic_image_lock (MonoDynamicImage *image)
226 {
227         MONO_TRY_BLOCKING;
228         mono_image_lock ((MonoImage*)image);
229         MONO_FINISH_TRY_BLOCKING;
230 }
231
232 static inline void
233 dynamic_image_unlock (MonoDynamicImage *image)
234 {
235         mono_image_unlock ((MonoImage*)image);
236 }
237
238 static void
239 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
240 {
241         MONO_REQ_GC_UNSAFE_MODE;
242
243         dynamic_image_lock (assembly);
244         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
245         dynamic_image_unlock (assembly);
246 }
247
248 static MonoObject*
249 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
250 {
251         MONO_REQ_GC_UNSAFE_MODE;
252
253         MonoObject *obj;
254
255         dynamic_image_lock (assembly);
256         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
257         dynamic_image_unlock (assembly);
258
259         return obj;
260 }
261
262 static void
263 sigbuffer_init (SigBuffer *buf, int size)
264 {
265         MONO_REQ_GC_NEUTRAL_MODE;
266
267         buf->buf = g_malloc (size);
268         buf->p = buf->buf;
269         buf->end = buf->buf + size;
270 }
271
272 static void
273 sigbuffer_make_room (SigBuffer *buf, int size)
274 {
275         MONO_REQ_GC_NEUTRAL_MODE;
276
277         if (buf->end - buf->p < size) {
278                 int new_size = buf->end - buf->buf + size + 32;
279                 char *p = g_realloc (buf->buf, new_size);
280                 size = buf->p - buf->buf;
281                 buf->buf = p;
282                 buf->p = p + size;
283                 buf->end = buf->buf + new_size;
284         }
285 }
286
287 static void
288 sigbuffer_add_value (SigBuffer *buf, guint32 val)
289 {
290         MONO_REQ_GC_NEUTRAL_MODE;
291
292         sigbuffer_make_room (buf, 6);
293         mono_metadata_encode_value (val, buf->p, &buf->p);
294 }
295
296 static void
297 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
298 {
299         MONO_REQ_GC_NEUTRAL_MODE;
300
301         sigbuffer_make_room (buf, 1);
302         buf->p [0] = val;
303         buf->p++;
304 }
305
306 static void
307 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
308 {
309         MONO_REQ_GC_NEUTRAL_MODE;
310
311         sigbuffer_make_room (buf, size);
312         memcpy (buf->p, p, size);
313         buf->p += size;
314 }
315
316 static void
317 sigbuffer_free (SigBuffer *buf)
318 {
319         MONO_REQ_GC_NEUTRAL_MODE;
320
321         g_free (buf->buf);
322 }
323
324 #ifndef DISABLE_REFLECTION_EMIT
325 /**
326  * mp_g_alloc:
327  *
328  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
329  * from the C heap.
330  */
331 static gpointer
332 image_g_malloc (MonoImage *image, guint size)
333 {
334         MONO_REQ_GC_NEUTRAL_MODE;
335
336         if (image)
337                 return mono_image_alloc (image, size);
338         else
339                 return g_malloc (size);
340 }
341 #endif /* !DISABLE_REFLECTION_EMIT */
342
343 /**
344  * image_g_alloc0:
345  *
346  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
347  * from the C heap.
348  */
349 static gpointer
350 image_g_malloc0 (MonoImage *image, guint size)
351 {
352         MONO_REQ_GC_NEUTRAL_MODE;
353
354         if (image)
355                 return mono_image_alloc0 (image, size);
356         else
357                 return g_malloc0 (size);
358 }
359
360 #ifndef DISABLE_REFLECTION_EMIT
361 static char*
362 image_strdup (MonoImage *image, const char *s)
363 {
364         MONO_REQ_GC_NEUTRAL_MODE;
365
366         if (image)
367                 return mono_image_strdup (image, s);
368         else
369                 return g_strdup (s);
370 }
371 #endif
372
373 #define image_g_new(image,struct_type, n_structs)               \
374     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
375
376 #define image_g_new0(image,struct_type, n_structs)              \
377     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
378
379
380 static void
381 alloc_table (MonoDynamicTable *table, guint nrows)
382 {
383         MONO_REQ_GC_NEUTRAL_MODE;
384
385         table->rows = nrows;
386         g_assert (table->columns);
387         if (nrows + 1 >= table->alloc_rows) {
388                 while (nrows + 1 >= table->alloc_rows) {
389                         if (table->alloc_rows == 0)
390                                 table->alloc_rows = 16;
391                         else
392                                 table->alloc_rows *= 2;
393                 }
394
395                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
396         }
397 }
398
399 static void
400 make_room_in_stream (MonoDynamicStream *stream, int size)
401 {
402         MONO_REQ_GC_NEUTRAL_MODE;
403
404         if (size <= stream->alloc_size)
405                 return;
406         
407         while (stream->alloc_size <= size) {
408                 if (stream->alloc_size < 4096)
409                         stream->alloc_size = 4096;
410                 else
411                         stream->alloc_size *= 2;
412         }
413         
414         stream->data = g_realloc (stream->data, stream->alloc_size);
415 }
416
417 static guint32
418 string_heap_insert (MonoDynamicStream *sh, const char *str)
419 {
420         MONO_REQ_GC_NEUTRAL_MODE;
421
422         guint32 idx;
423         guint32 len;
424         gpointer oldkey, oldval;
425
426         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
427                 return GPOINTER_TO_UINT (oldval);
428
429         len = strlen (str) + 1;
430         idx = sh->index;
431         
432         make_room_in_stream (sh, idx + len);
433
434         /*
435          * We strdup the string even if we already copy them in sh->data
436          * so that the string pointers in the hash remain valid even if
437          * we need to realloc sh->data. We may want to avoid that later.
438          */
439         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
440         memcpy (sh->data + idx, str, len);
441         sh->index += len;
442         return idx;
443 }
444
445 static guint32
446 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
447 {
448         MONO_REQ_GC_UNSAFE_MODE;
449
450         char *name = mono_string_to_utf8 (str);
451         guint32 idx;
452         idx = string_heap_insert (sh, name);
453         g_free (name);
454         return idx;
455 }
456
457 #ifndef DISABLE_REFLECTION_EMIT
458 static void
459 string_heap_init (MonoDynamicStream *sh)
460 {
461         MONO_REQ_GC_NEUTRAL_MODE;
462
463         sh->index = 0;
464         sh->alloc_size = 4096;
465         sh->data = g_malloc (4096);
466         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
467         string_heap_insert (sh, "");
468 }
469 #endif
470
471 static guint32
472 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
473 {
474         MONO_REQ_GC_NEUTRAL_MODE;
475
476         guint32 idx;
477         
478         make_room_in_stream (stream, stream->index + len);
479         memcpy (stream->data + stream->index, data, len);
480         idx = stream->index;
481         stream->index += len;
482         /* 
483          * align index? Not without adding an additional param that controls it since
484          * we may store a blob value in pieces.
485          */
486         return idx;
487 }
488
489 static guint32
490 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
491 {
492         MONO_REQ_GC_NEUTRAL_MODE;
493
494         guint32 idx;
495         
496         make_room_in_stream (stream, stream->index + len);
497         memset (stream->data + stream->index, 0, len);
498         idx = stream->index;
499         stream->index += len;
500         return idx;
501 }
502
503 static void
504 stream_data_align (MonoDynamicStream *stream)
505 {
506         MONO_REQ_GC_NEUTRAL_MODE;
507
508         char buf [4] = {0};
509         guint32 count = stream->index % 4;
510
511         /* we assume the stream data will be aligned */
512         if (count)
513                 mono_image_add_stream_data (stream, buf, 4 - count);
514 }
515
516 #ifndef DISABLE_REFLECTION_EMIT
517 static int
518 mono_blob_entry_hash (const char* str)
519 {
520         MONO_REQ_GC_NEUTRAL_MODE;
521
522         guint len, h;
523         const char *end;
524         len = mono_metadata_decode_blob_size (str, &str);
525         if (len > 0) {
526                 end = str + len;
527                 h = *str;
528                 for (str += 1; str < end; str++)
529                         h = (h << 5) - h + *str;
530                 return h;
531         } else {
532                 return 0;
533         }
534 }
535
536 static gboolean
537 mono_blob_entry_equal (const char *str1, const char *str2) {
538         MONO_REQ_GC_NEUTRAL_MODE;
539
540         int len, len2;
541         const char *end1;
542         const char *end2;
543         len = mono_metadata_decode_blob_size (str1, &end1);
544         len2 = mono_metadata_decode_blob_size (str2, &end2);
545         if (len != len2)
546                 return 0;
547         return memcmp (end1, end2, len) == 0;
548 }
549 #endif
550 static guint32
551 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
552 {
553         MONO_REQ_GC_NEUTRAL_MODE;
554
555         guint32 idx;
556         char *copy;
557         gpointer oldkey, oldval;
558
559         copy = g_malloc (s1+s2);
560         memcpy (copy, b1, s1);
561         memcpy (copy + s1, b2, s2);
562         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
563                 g_free (copy);
564                 idx = GPOINTER_TO_UINT (oldval);
565         } else {
566                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
567                 mono_image_add_stream_data (&assembly->blob, b2, s2);
568                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
569         }
570         return idx;
571 }
572
573 static guint32
574 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
575 {
576         MONO_REQ_GC_NEUTRAL_MODE;
577
578         char blob_size [8];
579         char *b = blob_size;
580         guint32 size = buf->p - buf->buf;
581         /* store length */
582         g_assert (size <= (buf->end - buf->buf));
583         mono_metadata_encode_value (size, b, &b);
584         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
585 }
586
587 /*
588  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
589  * dest may be misaligned.
590  */
591 static void
592 swap_with_size (char *dest, const char* val, int len, int nelem) {
593         MONO_REQ_GC_NEUTRAL_MODE;
594 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
595         int elem;
596
597         for (elem = 0; elem < nelem; ++elem) {
598                 switch (len) {
599                 case 1:
600                         *dest = *val;
601                         break;
602                 case 2:
603                         dest [0] = val [1];
604                         dest [1] = val [0];
605                         break;
606                 case 4:
607                         dest [0] = val [3];
608                         dest [1] = val [2];
609                         dest [2] = val [1];
610                         dest [3] = val [0];
611                         break;
612                 case 8:
613                         dest [0] = val [7];
614                         dest [1] = val [6];
615                         dest [2] = val [5];
616                         dest [3] = val [4];
617                         dest [4] = val [3];
618                         dest [5] = val [2];
619                         dest [6] = val [1];
620                         dest [7] = val [0];
621                         break;
622                 default:
623                         g_assert_not_reached ();
624                 }
625                 dest += len;
626                 val += len;
627         }
628 #else
629         memcpy (dest, val, len * nelem);
630 #endif
631 }
632
633 static guint32
634 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
635 {
636         MONO_REQ_GC_UNSAFE_MODE;
637         
638         char blob_size [64];
639         char *b = blob_size;
640         guint32 idx = 0, len;
641
642         len = str->length * 2;
643         mono_metadata_encode_value (len, b, &b);
644 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
645         {
646                 char *swapped = g_malloc (2 * mono_string_length (str));
647                 const char *p = (const char*)mono_string_chars (str);
648
649                 swap_with_size (swapped, p, 2, mono_string_length (str));
650                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
651                 g_free (swapped);
652         }
653 #else
654         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
655 #endif
656         return idx;
657 }
658
659 #ifndef DISABLE_REFLECTION_EMIT
660 static MonoClass *
661 default_class_from_mono_type (MonoType *type)
662 {
663         MONO_REQ_GC_NEUTRAL_MODE;
664
665         switch (type->type) {
666         case MONO_TYPE_OBJECT:
667                 return mono_defaults.object_class;
668         case MONO_TYPE_VOID:
669                 return mono_defaults.void_class;
670         case MONO_TYPE_BOOLEAN:
671                 return mono_defaults.boolean_class;
672         case MONO_TYPE_CHAR:
673                 return mono_defaults.char_class;
674         case MONO_TYPE_I1:
675                 return mono_defaults.sbyte_class;
676         case MONO_TYPE_U1:
677                 return mono_defaults.byte_class;
678         case MONO_TYPE_I2:
679                 return mono_defaults.int16_class;
680         case MONO_TYPE_U2:
681                 return mono_defaults.uint16_class;
682         case MONO_TYPE_I4:
683                 return mono_defaults.int32_class;
684         case MONO_TYPE_U4:
685                 return mono_defaults.uint32_class;
686         case MONO_TYPE_I:
687                 return mono_defaults.int_class;
688         case MONO_TYPE_U:
689                 return mono_defaults.uint_class;
690         case MONO_TYPE_I8:
691                 return mono_defaults.int64_class;
692         case MONO_TYPE_U8:
693                 return mono_defaults.uint64_class;
694         case MONO_TYPE_R4:
695                 return mono_defaults.single_class;
696         case MONO_TYPE_R8:
697                 return mono_defaults.double_class;
698         case MONO_TYPE_STRING:
699                 return mono_defaults.string_class;
700         default:
701                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
702                 g_assert_not_reached ();
703         }
704         
705         return NULL;
706 }
707 #endif
708
709 /*
710  * mono_class_get_ref_info:
711  *
712  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
713  */
714 gpointer
715 mono_class_get_ref_info (MonoClass *klass)
716 {
717         MONO_REQ_GC_UNSAFE_MODE;
718
719         if (klass->ref_info_handle == 0)
720                 return NULL;
721         else
722                 return mono_gchandle_get_target (klass->ref_info_handle);
723 }
724
725 void
726 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
727 {
728         MONO_REQ_GC_UNSAFE_MODE;
729
730         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
731         g_assert (klass->ref_info_handle != 0);
732 }
733
734 void
735 mono_class_free_ref_info (MonoClass *klass)
736 {
737         MONO_REQ_GC_NEUTRAL_MODE;
738
739         if (klass->ref_info_handle) {
740                 mono_gchandle_free (klass->ref_info_handle);
741                 klass->ref_info_handle = 0;
742         }
743 }
744
745 static void
746 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
747 {
748         MONO_REQ_GC_NEUTRAL_MODE;
749
750         int i;
751         MonoGenericInst *class_inst;
752         MonoClass *klass;
753
754         g_assert (gclass);
755
756         class_inst = gclass->context.class_inst;
757
758         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
759         klass = gclass->container_class;
760         sigbuffer_add_value (buf, klass->byval_arg.type);
761         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
762
763         sigbuffer_add_value (buf, class_inst->type_argc);
764         for (i = 0; i < class_inst->type_argc; ++i)
765                 encode_type (assembly, class_inst->type_argv [i], buf);
766
767 }
768
769 static void
770 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
771 {
772         MONO_REQ_GC_NEUTRAL_MODE;
773
774         if (!type) {
775                 g_assert_not_reached ();
776                 return;
777         }
778                 
779         if (type->byref)
780                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
781
782         switch (type->type){
783         case MONO_TYPE_VOID:
784         case MONO_TYPE_BOOLEAN:
785         case MONO_TYPE_CHAR:
786         case MONO_TYPE_I1:
787         case MONO_TYPE_U1:
788         case MONO_TYPE_I2:
789         case MONO_TYPE_U2:
790         case MONO_TYPE_I4:
791         case MONO_TYPE_U4:
792         case MONO_TYPE_I8:
793         case MONO_TYPE_U8:
794         case MONO_TYPE_R4:
795         case MONO_TYPE_R8:
796         case MONO_TYPE_I:
797         case MONO_TYPE_U:
798         case MONO_TYPE_STRING:
799         case MONO_TYPE_OBJECT:
800         case MONO_TYPE_TYPEDBYREF:
801                 sigbuffer_add_value (buf, type->type);
802                 break;
803         case MONO_TYPE_PTR:
804                 sigbuffer_add_value (buf, type->type);
805                 encode_type (assembly, type->data.type, buf);
806                 break;
807         case MONO_TYPE_SZARRAY:
808                 sigbuffer_add_value (buf, type->type);
809                 encode_type (assembly, &type->data.klass->byval_arg, buf);
810                 break;
811         case MONO_TYPE_VALUETYPE:
812         case MONO_TYPE_CLASS: {
813                 MonoClass *k = mono_class_from_mono_type (type);
814
815                 if (k->generic_container) {
816                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
817                         encode_generic_class (assembly, gclass, buf);
818                 } else {
819                         /*
820                          * Make sure we use the correct type.
821                          */
822                         sigbuffer_add_value (buf, k->byval_arg.type);
823                         /*
824                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
825                          * otherwise two typerefs could point to the same type, leading to
826                          * verification errors.
827                          */
828                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
829                 }
830                 break;
831         }
832         case MONO_TYPE_ARRAY:
833                 sigbuffer_add_value (buf, type->type);
834                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
835                 sigbuffer_add_value (buf, type->data.array->rank);
836                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
837                 sigbuffer_add_value (buf, 0);
838                 break;
839         case MONO_TYPE_GENERICINST:
840                 encode_generic_class (assembly, type->data.generic_class, buf);
841                 break;
842         case MONO_TYPE_VAR:
843         case MONO_TYPE_MVAR:
844                 sigbuffer_add_value (buf, type->type);
845                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
846                 break;
847         default:
848                 g_error ("need to encode type %x", type->type);
849         }
850 }
851
852 static void
853 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
854 {
855         MONO_REQ_GC_UNSAFE_MODE;
856
857         if (!type) {
858                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
859                 return;
860         }
861
862         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
863 }
864
865 static void
866 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
867 {
868         MONO_REQ_GC_UNSAFE_MODE;
869
870         int i;
871
872         if (modreq) {
873                 for (i = 0; i < mono_array_length (modreq); ++i) {
874                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
875                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
876                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
877                 }
878         }
879         if (modopt) {
880                 for (i = 0; i < mono_array_length (modopt); ++i) {
881                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
882                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
883                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
884                 }
885         }
886 }
887
888 #ifndef DISABLE_REFLECTION_EMIT
889 static guint32
890 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
891 {
892         MONO_REQ_GC_UNSAFE_MODE;
893
894         SigBuffer buf;
895         int i;
896         guint32 nparams =  sig->param_count;
897         guint32 idx;
898
899         if (!assembly->save)
900                 return 0;
901
902         sigbuffer_init (&buf, 32);
903         /*
904          * FIXME: vararg, explicit_this, differenc call_conv values...
905          */
906         idx = sig->call_convention;
907         if (sig->hasthis)
908                 idx |= 0x20; /* hasthis */
909         if (sig->generic_param_count)
910                 idx |= 0x10; /* generic */
911         sigbuffer_add_byte (&buf, idx);
912         if (sig->generic_param_count)
913                 sigbuffer_add_value (&buf, sig->generic_param_count);
914         sigbuffer_add_value (&buf, nparams);
915         encode_type (assembly, sig->ret, &buf);
916         for (i = 0; i < nparams; ++i) {
917                 if (i == sig->sentinelpos)
918                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
919                 encode_type (assembly, sig->params [i], &buf);
920         }
921         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
922         sigbuffer_free (&buf);
923         return idx;
924 }
925 #endif
926
927 static guint32
928 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
929 {
930         MONO_REQ_GC_UNSAFE_MODE;
931
932         /*
933          * FIXME: reuse code from method_encode_signature().
934          */
935         SigBuffer buf;
936         int i;
937         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
938         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
939         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
940         guint32 idx;
941
942         sigbuffer_init (&buf, 32);
943         /* LAMESPEC: all the call conv spec is foobared */
944         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
945         if (mb->call_conv & 2)
946                 idx |= 0x5; /* vararg */
947         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
948                 idx |= 0x20; /* hasthis */
949         if (ngparams)
950                 idx |= 0x10; /* generic */
951         sigbuffer_add_byte (&buf, idx);
952         if (ngparams)
953                 sigbuffer_add_value (&buf, ngparams);
954         sigbuffer_add_value (&buf, nparams + notypes);
955         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
956         encode_reflection_type (assembly, mb->rtype, &buf);
957         for (i = 0; i < nparams; ++i) {
958                 MonoArray *modreq = NULL;
959                 MonoArray *modopt = NULL;
960                 MonoReflectionType *pt;
961
962                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
963                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
964                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
965                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
966                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
967                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
968                 encode_reflection_type (assembly, pt, &buf);
969         }
970         if (notypes)
971                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
972         for (i = 0; i < notypes; ++i) {
973                 MonoReflectionType *pt;
974
975                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
976                 encode_reflection_type (assembly, pt, &buf);
977         }
978
979         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
980         sigbuffer_free (&buf);
981         return idx;
982 }
983
984 static guint32
985 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
986 {
987         MONO_REQ_GC_UNSAFE_MODE;
988
989         MonoDynamicTable *table;
990         guint32 *values;
991         guint32 idx, sig_idx;
992         guint nl = mono_array_length (ilgen->locals);
993         SigBuffer buf;
994         int i;
995
996         sigbuffer_init (&buf, 32);
997         sigbuffer_add_value (&buf, 0x07);
998         sigbuffer_add_value (&buf, nl);
999         for (i = 0; i < nl; ++i) {
1000                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1001                 
1002                 if (lb->is_pinned)
1003                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1004                 
1005                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1006         }
1007         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1008         sigbuffer_free (&buf);
1009
1010         if (assembly->standalonesig_cache == NULL)
1011                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1012         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1013         if (idx)
1014                 return idx;
1015
1016         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1017         idx = table->next_idx ++;
1018         table->rows ++;
1019         alloc_table (table, table->rows);
1020         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1021
1022         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1023
1024         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1025
1026         return idx;
1027 }
1028
1029 static guint32
1030 method_count_clauses (MonoReflectionILGen *ilgen)
1031 {
1032         MONO_REQ_GC_UNSAFE_MODE;
1033
1034         guint32 num_clauses = 0;
1035         int i;
1036
1037         MonoILExceptionInfo *ex_info;
1038         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1039                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1040                 if (ex_info->handlers)
1041                         num_clauses += mono_array_length (ex_info->handlers);
1042                 else
1043                         num_clauses++;
1044         }
1045
1046         return num_clauses;
1047 }
1048
1049 #ifndef DISABLE_REFLECTION_EMIT
1050 static MonoExceptionClause*
1051 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1052 {
1053         MONO_REQ_GC_UNSAFE_MODE;
1054
1055         MonoExceptionClause *clauses;
1056         MonoExceptionClause *clause;
1057         MonoILExceptionInfo *ex_info;
1058         MonoILExceptionBlock *ex_block;
1059         guint32 finally_start;
1060         int i, j, clause_index;;
1061
1062         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1063
1064         clause_index = 0;
1065         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1066                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1067                 finally_start = ex_info->start + ex_info->len;
1068                 if (!ex_info->handlers)
1069                         continue;
1070                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1071                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1072                         clause = &(clauses [clause_index]);
1073
1074                         clause->flags = ex_block->type;
1075                         clause->try_offset = ex_info->start;
1076
1077                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1078                                 clause->try_len = finally_start - ex_info->start;
1079                         else
1080                                 clause->try_len = ex_info->len;
1081                         clause->handler_offset = ex_block->start;
1082                         clause->handler_len = ex_block->len;
1083                         if (ex_block->extype) {
1084                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1085                         } else {
1086                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1087                                         clause->data.filter_offset = ex_block->filter_offset;
1088                                 else
1089                                         clause->data.filter_offset = 0;
1090                         }
1091                         finally_start = ex_block->start + ex_block->len;
1092
1093                         clause_index ++;
1094                 }
1095         }
1096
1097         return clauses;
1098 }
1099 #endif /* !DISABLE_REFLECTION_EMIT */
1100
1101 static guint32
1102 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1103 {
1104         MONO_REQ_GC_UNSAFE_MODE;
1105
1106         char flags = 0;
1107         guint32 idx;
1108         guint32 code_size;
1109         gint32 max_stack, i;
1110         gint32 num_locals = 0;
1111         gint32 num_exception = 0;
1112         gint maybe_small;
1113         guint32 fat_flags;
1114         char fat_header [12];
1115         guint32 int_value;
1116         guint16 short_value;
1117         guint32 local_sig = 0;
1118         guint32 header_size = 12;
1119         MonoArray *code;
1120
1121         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1122                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1123                 return 0;
1124
1125         /*if (mb->name)
1126                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1127         if (mb->ilgen) {
1128                 code = mb->ilgen->code;
1129                 code_size = mb->ilgen->code_len;
1130                 max_stack = mb->ilgen->max_stack;
1131                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1132                 if (mb->ilgen->ex_handlers)
1133                         num_exception = method_count_clauses (mb->ilgen);
1134         } else {
1135                 code = mb->code;
1136                 if (code == NULL){
1137                         char *name = mono_string_to_utf8 (mb->name);
1138                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1139                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1140                         g_free (str);
1141                         g_free (name);
1142                         mono_raise_exception (exception);
1143                 }
1144
1145                 code_size = mono_array_length (code);
1146                 max_stack = 8; /* we probably need to run a verifier on the code... */
1147         }
1148
1149         stream_data_align (&assembly->code);
1150
1151         /* check for exceptions, maxstack, locals */
1152         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1153         if (maybe_small) {
1154                 if (code_size < 64 && !(code_size & 1)) {
1155                         flags = (code_size << 2) | 0x2;
1156                 } else if (code_size < 32 && (code_size & 1)) {
1157                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1158                 } else {
1159                         goto fat_header;
1160                 }
1161                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1162                 /* add to the fixup todo list */
1163                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1164                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1165                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1166                 return assembly->text_rva + idx;
1167         } 
1168 fat_header:
1169         if (num_locals)
1170                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1171         /* 
1172          * FIXME: need to set also the header size in fat_flags.
1173          * (and more sects and init locals flags)
1174          */
1175         fat_flags =  0x03;
1176         if (num_exception)
1177                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1178         if (mb->init_locals)
1179                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1180         fat_header [0] = fat_flags;
1181         fat_header [1] = (header_size / 4 ) << 4;
1182         short_value = GUINT16_TO_LE (max_stack);
1183         memcpy (fat_header + 2, &short_value, 2);
1184         int_value = GUINT32_TO_LE (code_size);
1185         memcpy (fat_header + 4, &int_value, 4);
1186         int_value = GUINT32_TO_LE (local_sig);
1187         memcpy (fat_header + 8, &int_value, 4);
1188         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1189         /* add to the fixup todo list */
1190         if (mb->ilgen && mb->ilgen->num_token_fixups)
1191                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1192         
1193         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1194         if (num_exception) {
1195                 unsigned char sheader [4];
1196                 MonoILExceptionInfo * ex_info;
1197                 MonoILExceptionBlock * ex_block;
1198                 int j;
1199
1200                 stream_data_align (&assembly->code);
1201                 /* always use fat format for now */
1202                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1203                 num_exception *= 6 * sizeof (guint32);
1204                 num_exception += 4; /* include the size of the header */
1205                 sheader [1] = num_exception & 0xff;
1206                 sheader [2] = (num_exception >> 8) & 0xff;
1207                 sheader [3] = (num_exception >> 16) & 0xff;
1208                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1209                 /* fat header, so we are already aligned */
1210                 /* reverse order */
1211                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1212                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1213                         if (ex_info->handlers) {
1214                                 int finally_start = ex_info->start + ex_info->len;
1215                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1216                                         guint32 val;
1217                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1218                                         /* the flags */
1219                                         val = GUINT32_TO_LE (ex_block->type);
1220                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1221                                         /* try offset */
1222                                         val = GUINT32_TO_LE (ex_info->start);
1223                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1224                                         /* need fault, too, probably */
1225                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1226                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1227                                         else
1228                                                 val = GUINT32_TO_LE (ex_info->len);
1229                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1230                                         /* handler offset */
1231                                         val = GUINT32_TO_LE (ex_block->start);
1232                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1233                                         /* handler len */
1234                                         val = GUINT32_TO_LE (ex_block->len);
1235                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1236                                         finally_start = ex_block->start + ex_block->len;
1237                                         if (ex_block->extype) {
1238                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1239                                         } else {
1240                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1241                                                         val = ex_block->filter_offset;
1242                                                 else
1243                                                         val = 0;
1244                                         }
1245                                         val = GUINT32_TO_LE (val);
1246                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1247                                         /*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", 
1248                                                         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);*/
1249                                 }
1250                         } else {
1251                                 g_error ("No clauses for ex info block %d", i);
1252                         }
1253                 }
1254         }
1255         return assembly->text_rva + idx;
1256 }
1257
1258 static guint32
1259 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1260 {
1261         MONO_REQ_GC_NEUTRAL_MODE;
1262
1263         int i;
1264         MonoDynamicTable *table;
1265         guint32 *values;
1266         
1267         table = &assembly->tables [table_idx];
1268
1269         g_assert (col < table->columns);
1270
1271         values = table->values + table->columns;
1272         for (i = 1; i <= table->rows; ++i) {
1273                 if (values [col] == token)
1274                         return i;
1275                 values += table->columns;
1276         }
1277         return 0;
1278 }
1279
1280 /*
1281  * LOCKING: Acquires the loader lock. 
1282  */
1283 static MonoCustomAttrInfo*
1284 lookup_custom_attr (MonoImage *image, gpointer member)
1285 {
1286         MONO_REQ_GC_NEUTRAL_MODE;
1287
1288         MonoCustomAttrInfo* res;
1289
1290         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1291
1292         if (!res)
1293                 return NULL;
1294
1295         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1296         res->cached = 0;
1297         return res;
1298 }
1299
1300 static gboolean
1301 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1302 {
1303         MONO_REQ_GC_UNSAFE_MODE;
1304
1305         /* FIXME: Need to do more checks */
1306         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1307                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1308
1309                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1310                         return FALSE;
1311         }
1312
1313         return TRUE;
1314 }
1315
1316 static MonoCustomAttrInfo*
1317 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1318 {
1319         MONO_REQ_GC_UNSAFE_MODE;
1320
1321         int i, index, count, not_visible;
1322         MonoCustomAttrInfo *ainfo;
1323         MonoReflectionCustomAttr *cattr;
1324
1325         if (!cattrs)
1326                 return NULL;
1327         /* FIXME: check in assembly the Run flag is set */
1328
1329         count = mono_array_length (cattrs);
1330
1331         /* Skip nonpublic attributes since MS.NET seems to do the same */
1332         /* FIXME: This needs to be done more globally */
1333         not_visible = 0;
1334         for (i = 0; i < count; ++i) {
1335                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1336                 if (!custom_attr_visible (image, cattr))
1337                         not_visible ++;
1338         }
1339         count -= not_visible;
1340
1341         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1342
1343         ainfo->image = image;
1344         ainfo->num_attrs = count;
1345         ainfo->cached = alloc_img != NULL;
1346         index = 0;
1347         for (i = 0; i < count; ++i) {
1348                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1349                 if (custom_attr_visible (image, cattr)) {
1350                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1351                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1352                         ainfo->attrs [index].ctor = cattr->ctor->method;
1353                         ainfo->attrs [index].data = saved;
1354                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1355                         index ++;
1356                 }
1357         }
1358
1359         return ainfo;
1360 }
1361
1362 #ifndef DISABLE_REFLECTION_EMIT
1363 /*
1364  * LOCKING: Acquires the loader lock. 
1365  */
1366 static void
1367 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1368 {
1369         MONO_REQ_GC_UNSAFE_MODE;
1370
1371         MonoCustomAttrInfo *ainfo, *tmp;
1372
1373         if (!cattrs || !mono_array_length (cattrs))
1374                 return;
1375
1376         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1377
1378         mono_loader_lock ();
1379         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1380         if (tmp)
1381                 mono_custom_attrs_free (tmp);
1382         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1383         mono_loader_unlock ();
1384
1385 }
1386 #endif
1387
1388 void
1389 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1390 {
1391         MONO_REQ_GC_NEUTRAL_MODE;
1392
1393         if (!ainfo->cached)
1394                 g_free (ainfo);
1395 }
1396
1397 /*
1398  * idx is the table index of the object
1399  * type is one of MONO_CUSTOM_ATTR_*
1400  */
1401 static void
1402 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1403 {
1404         MONO_REQ_GC_UNSAFE_MODE;
1405
1406         MonoDynamicTable *table;
1407         MonoReflectionCustomAttr *cattr;
1408         guint32 *values;
1409         guint32 count, i, token;
1410         char blob_size [6];
1411         char *p = blob_size;
1412         
1413         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1414         if (!cattrs)
1415                 return;
1416         count = mono_array_length (cattrs);
1417         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1418         table->rows += count;
1419         alloc_table (table, table->rows);
1420         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1421         idx <<= MONO_CUSTOM_ATTR_BITS;
1422         idx |= type;
1423         for (i = 0; i < count; ++i) {
1424                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1425                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1426                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1427                 type = mono_metadata_token_index (token);
1428                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1429                 switch (mono_metadata_token_table (token)) {
1430                 case MONO_TABLE_METHOD:
1431                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1432                         /*
1433                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1434                          * method, not the one returned by mono_image_create_token ().
1435                          */
1436                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1437                         break;
1438                 case MONO_TABLE_MEMBERREF:
1439                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1440                         break;
1441                 default:
1442                         g_warning ("got wrong token in custom attr");
1443                         continue;
1444                 }
1445                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1446                 p = blob_size;
1447                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1448                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1449                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1450                 values += MONO_CUSTOM_ATTR_SIZE;
1451                 ++table->next_idx;
1452         }
1453 }
1454
1455 static void
1456 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1457 {
1458         MONO_REQ_GC_UNSAFE_MODE;
1459
1460         MonoDynamicTable *table;
1461         guint32 *values;
1462         guint32 count, i, idx;
1463         MonoReflectionPermissionSet *perm;
1464
1465         if (!permissions)
1466                 return;
1467
1468         count = mono_array_length (permissions);
1469         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1470         table->rows += count;
1471         alloc_table (table, table->rows);
1472
1473         for (i = 0; i < mono_array_length (permissions); ++i) {
1474                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1475
1476                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1477
1478                 idx = mono_metadata_token_index (parent_token);
1479                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1480                 switch (mono_metadata_token_table (parent_token)) {
1481                 case MONO_TABLE_TYPEDEF:
1482                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1483                         break;
1484                 case MONO_TABLE_METHOD:
1485                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1486                         break;
1487                 case MONO_TABLE_ASSEMBLY:
1488                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1489                         break;
1490                 default:
1491                         g_assert_not_reached ();
1492                 }
1493
1494                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1495                 values [MONO_DECL_SECURITY_PARENT] = idx;
1496                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1497
1498                 ++table->next_idx;
1499         }
1500 }
1501
1502 /*
1503  * Fill in the MethodDef and ParamDef tables for a method.
1504  * This is used for both normal methods and constructors.
1505  */
1506 static void
1507 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1508 {
1509         MONO_REQ_GC_UNSAFE_MODE;
1510
1511         MonoDynamicTable *table;
1512         guint32 *values;
1513         guint i, count;
1514
1515         /* room in this table is already allocated */
1516         table = &assembly->tables [MONO_TABLE_METHOD];
1517         *mb->table_idx = table->next_idx ++;
1518         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1519         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1520         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1521         values [MONO_METHOD_FLAGS] = mb->attrs;
1522         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1523         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1524         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1525         
1526         table = &assembly->tables [MONO_TABLE_PARAM];
1527         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1528
1529         mono_image_add_decl_security (assembly, 
1530                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1531
1532         if (mb->pinfo) {
1533                 MonoDynamicTable *mtable;
1534                 guint32 *mvalues;
1535                 
1536                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1537                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1538                 
1539                 count = 0;
1540                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1541                         if (mono_array_get (mb->pinfo, gpointer, i))
1542                                 count++;
1543                 }
1544                 table->rows += count;
1545                 alloc_table (table, table->rows);
1546                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1547                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1548                         MonoReflectionParamBuilder *pb;
1549                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1550                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1551                                 values [MONO_PARAM_SEQUENCE] = i;
1552                                 if (pb->name != NULL) {
1553                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1554                                 } else {
1555                                         values [MONO_PARAM_NAME] = 0;
1556                                 }
1557                                 values += MONO_PARAM_SIZE;
1558                                 if (pb->marshal_info) {
1559                                         mtable->rows++;
1560                                         alloc_table (mtable, mtable->rows);
1561                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1562                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1563                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1564                                 }
1565                                 pb->table_idx = table->next_idx++;
1566                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1567                                         guint32 field_type = 0;
1568                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1569                                         mtable->rows ++;
1570                                         alloc_table (mtable, mtable->rows);
1571                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1572                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1573                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1574                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1575                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1576                                 }
1577                         }
1578                 }
1579         }
1580 }
1581
1582 #ifndef DISABLE_REFLECTION_EMIT
1583 static void
1584 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1585 {
1586         MONO_REQ_GC_UNSAFE_MODE;
1587
1588         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1589
1590         rmb->ilgen = mb->ilgen;
1591         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1592         rmb->parameters = mb->parameters;
1593         rmb->generic_params = mb->generic_params;
1594         rmb->generic_container = mb->generic_container;
1595         rmb->opt_types = NULL;
1596         rmb->pinfo = mb->pinfo;
1597         rmb->attrs = mb->attrs;
1598         rmb->iattrs = mb->iattrs;
1599         rmb->call_conv = mb->call_conv;
1600         rmb->code = mb->code;
1601         rmb->type = mb->type;
1602         rmb->name = mb->name;
1603         rmb->table_idx = &mb->table_idx;
1604         rmb->init_locals = mb->init_locals;
1605         rmb->skip_visibility = FALSE;
1606         rmb->return_modreq = mb->return_modreq;
1607         rmb->return_modopt = mb->return_modopt;
1608         rmb->param_modreq = mb->param_modreq;
1609         rmb->param_modopt = mb->param_modopt;
1610         rmb->permissions = mb->permissions;
1611         rmb->mhandle = mb->mhandle;
1612         rmb->nrefs = 0;
1613         rmb->refs = NULL;
1614
1615         if (mb->dll) {
1616                 rmb->charset = mb->charset;
1617                 rmb->extra_flags = mb->extra_flags;
1618                 rmb->native_cc = mb->native_cc;
1619                 rmb->dllentry = mb->dllentry;
1620                 rmb->dll = mb->dll;
1621         }
1622 }
1623
1624 static void
1625 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1626 {
1627         MONO_REQ_GC_UNSAFE_MODE;
1628
1629         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1630
1631         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1632
1633         rmb->ilgen = mb->ilgen;
1634         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1635         rmb->parameters = mb->parameters;
1636         rmb->generic_params = NULL;
1637         rmb->generic_container = NULL;
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 = NULL;
1644         rmb->type = mb->type;
1645         rmb->name = mono_string_new (mono_domain_get (), name);
1646         rmb->table_idx = &mb->table_idx;
1647         rmb->init_locals = mb->init_locals;
1648         rmb->skip_visibility = FALSE;
1649         rmb->return_modreq = NULL;
1650         rmb->return_modopt = NULL;
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
1659 static void
1660 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1661 {
1662         MONO_REQ_GC_UNSAFE_MODE;
1663
1664         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1665
1666         rmb->ilgen = mb->ilgen;
1667         rmb->rtype = mb->rtype;
1668         rmb->parameters = mb->parameters;
1669         rmb->generic_params = NULL;
1670         rmb->generic_container = NULL;
1671         rmb->opt_types = NULL;
1672         rmb->pinfo = NULL;
1673         rmb->attrs = mb->attrs;
1674         rmb->iattrs = 0;
1675         rmb->call_conv = mb->call_conv;
1676         rmb->code = NULL;
1677         rmb->type = (MonoObject *) mb->owner;
1678         rmb->name = mb->name;
1679         rmb->table_idx = NULL;
1680         rmb->init_locals = mb->init_locals;
1681         rmb->skip_visibility = mb->skip_visibility;
1682         rmb->return_modreq = NULL;
1683         rmb->return_modopt = NULL;
1684         rmb->param_modreq = NULL;
1685         rmb->param_modopt = NULL;
1686         rmb->permissions = NULL;
1687         rmb->mhandle = mb->mhandle;
1688         rmb->nrefs = 0;
1689         rmb->refs = NULL;
1690 }       
1691 #endif
1692
1693 static void
1694 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1695 {
1696         MONO_REQ_GC_UNSAFE_MODE;
1697
1698         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1699         MonoDynamicTable *table;
1700         guint32 *values;
1701         guint32 tok;
1702         MonoReflectionMethod *m;
1703         int i;
1704
1705         if (!mb->override_methods)
1706                 return;
1707
1708         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1709                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1710
1711                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1712                 table->rows ++;
1713                 alloc_table (table, table->rows);
1714                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1715                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1716                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1717
1718                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1719                 switch (mono_metadata_token_table (tok)) {
1720                 case MONO_TABLE_MEMBERREF:
1721                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1722                         break;
1723                 case MONO_TABLE_METHOD:
1724                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1725                         break;
1726                 default:
1727                         g_assert_not_reached ();
1728                 }
1729                 values [MONO_METHODIMPL_DECLARATION] = tok;
1730         }
1731 }
1732
1733 #ifndef DISABLE_REFLECTION_EMIT
1734 static void
1735 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1736 {
1737         MONO_REQ_GC_UNSAFE_MODE;
1738
1739         MonoDynamicTable *table;
1740         guint32 *values;
1741         ReflectionMethodBuilder rmb;
1742         int i;
1743
1744         reflection_methodbuilder_from_method_builder (&rmb, mb);
1745
1746         mono_image_basic_method (&rmb, assembly);
1747         mb->table_idx = *rmb.table_idx;
1748
1749         if (mb->dll) { /* It's a P/Invoke method */
1750                 guint32 moduleref;
1751                 /* map CharSet values to on-disk values */
1752                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1753                 int extra_flags = mb->extra_flags;
1754                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1755                 table->rows ++;
1756                 alloc_table (table, table->rows);
1757                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1758                 
1759                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1760                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1761                 if (mb->dllentry)
1762                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1763                 else
1764                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1765                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1766                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1767                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1768                         table->rows ++;
1769                         alloc_table (table, table->rows);
1770                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1771                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1772                 }
1773         }
1774
1775         if (mb->generic_params) {
1776                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1777                 table->rows += mono_array_length (mb->generic_params);
1778                 alloc_table (table, table->rows);
1779                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1780                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1781
1782                         mono_image_get_generic_param_info (
1783                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1784                 }
1785         }
1786
1787 }
1788
1789 static void
1790 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1791 {
1792         MONO_REQ_GC_UNSAFE_MODE;
1793
1794         ReflectionMethodBuilder rmb;
1795
1796         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1797
1798         mono_image_basic_method (&rmb, assembly);
1799         mb->table_idx = *rmb.table_idx;
1800 }
1801 #endif
1802
1803 static char*
1804 type_get_fully_qualified_name (MonoType *type)
1805 {
1806         MONO_REQ_GC_NEUTRAL_MODE;
1807
1808         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1809 }
1810
1811 static char*
1812 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1813 {
1814         MONO_REQ_GC_UNSAFE_MODE;
1815
1816         MonoClass *klass;
1817         MonoAssembly *ta;
1818
1819         klass = mono_class_from_mono_type (type);
1820         if (!klass) 
1821                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1822         ta = klass->image->assembly;
1823         if (assembly_is_dynamic (ta) || (ta == ass)) {
1824                 if (klass->generic_class || klass->generic_container)
1825                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1826                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1827                 else
1828                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1829         }
1830
1831         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1832 }
1833
1834 #ifndef DISABLE_REFLECTION_EMIT
1835 /*field_image is the image to which the eventual custom mods have been encoded against*/
1836 static guint32
1837 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1838 {
1839         MONO_REQ_GC_NEUTRAL_MODE;
1840
1841         SigBuffer buf;
1842         guint32 idx, i, token;
1843
1844         if (!assembly->save)
1845                 return 0;
1846
1847         sigbuffer_init (&buf, 32);
1848         
1849         sigbuffer_add_value (&buf, 0x06);
1850         /* encode custom attributes before the type */
1851         if (type->num_mods) {
1852                 for (i = 0; i < type->num_mods; ++i) {
1853                         if (field_image) {
1854                                 MonoError error;
1855                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1856                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1857
1858                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1859                         } else {
1860                                 token = type->modifiers [i].token;
1861                         }
1862
1863                         if (type->modifiers [i].required)
1864                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1865                         else
1866                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1867
1868                         sigbuffer_add_value (&buf, token);
1869                 }
1870         }
1871         encode_type (assembly, type, &buf);
1872         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1873         sigbuffer_free (&buf);
1874         return idx;
1875 }
1876 #endif
1877
1878 static guint32
1879 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1880 {
1881         MONO_REQ_GC_UNSAFE_MODE;
1882
1883         SigBuffer buf;
1884         guint32 idx;
1885         guint32 typespec = 0;
1886         MonoType *type;
1887         MonoClass *klass;
1888
1889         init_type_builder_generics (fb->type);
1890
1891         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1892         klass = mono_class_from_mono_type (type);
1893
1894         sigbuffer_init (&buf, 32);
1895         
1896         sigbuffer_add_value (&buf, 0x06);
1897         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1898         /* encode custom attributes before the type */
1899
1900         if (klass->generic_container)
1901                 typespec = create_typespec (assembly, type);
1902
1903         if (typespec) {
1904                 MonoGenericClass *gclass;
1905                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1906                 encode_generic_class (assembly, gclass, &buf);
1907         } else {
1908                 encode_type (assembly, type, &buf);
1909         }
1910         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1911         sigbuffer_free (&buf);
1912         return idx;
1913 }
1914
1915 static guint32
1916 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
1917 {
1918         MONO_REQ_GC_UNSAFE_MODE;
1919
1920         char blob_size [64];
1921         char *b = blob_size;
1922         char *box_val;
1923         char* buf;
1924         guint32 idx = 0, len = 0, dummy = 0;
1925
1926         buf = g_malloc (64);
1927         if (!val) {
1928                 *ret_type = MONO_TYPE_CLASS;
1929                 len = 4;
1930                 box_val = (char*)&dummy;
1931         } else {
1932                 box_val = ((char*)val) + sizeof (MonoObject);
1933                 *ret_type = val->vtable->klass->byval_arg.type;
1934         }
1935 handle_enum:
1936         switch (*ret_type) {
1937         case MONO_TYPE_BOOLEAN:
1938         case MONO_TYPE_U1:
1939         case MONO_TYPE_I1:
1940                 len = 1;
1941                 break;
1942         case MONO_TYPE_CHAR:
1943         case MONO_TYPE_U2:
1944         case MONO_TYPE_I2:
1945                 len = 2;
1946                 break;
1947         case MONO_TYPE_U4:
1948         case MONO_TYPE_I4:
1949         case MONO_TYPE_R4:
1950                 len = 4;
1951                 break;
1952         case MONO_TYPE_U8:
1953         case MONO_TYPE_I8:
1954                 len = 8;
1955                 break;
1956         case MONO_TYPE_R8:
1957                 len = 8;
1958                 break;
1959         case MONO_TYPE_VALUETYPE: {
1960                 MonoClass *klass = val->vtable->klass;
1961                 
1962                 if (klass->enumtype) {
1963                         *ret_type = mono_class_enum_basetype (klass)->type;
1964                         goto handle_enum;
1965                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1966                         len = 8;
1967                 } else 
1968                         g_error ("we can't encode valuetypes, we should have never reached this line");
1969                 break;
1970         }
1971         case MONO_TYPE_CLASS:
1972                 break;
1973         case MONO_TYPE_STRING: {
1974                 MonoString *str = (MonoString*)val;
1975                 /* there is no signature */
1976                 len = str->length * 2;
1977                 mono_metadata_encode_value (len, b, &b);
1978 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1979                 {
1980                         char *swapped = g_malloc (2 * mono_string_length (str));
1981                         const char *p = (const char*)mono_string_chars (str);
1982
1983                         swap_with_size (swapped, p, 2, mono_string_length (str));
1984                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1985                         g_free (swapped);
1986                 }
1987 #else
1988                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1989 #endif
1990
1991                 g_free (buf);
1992                 return idx;
1993         }
1994         case MONO_TYPE_GENERICINST:
1995                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1996                 goto handle_enum;
1997         default:
1998                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1999         }
2000
2001         /* there is no signature */
2002         mono_metadata_encode_value (len, b, &b);
2003 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2004         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2005         swap_with_size (blob_size, box_val, len, 1);
2006         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2007 #else
2008         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2009 #endif
2010
2011         g_free (buf);
2012         return idx;
2013 }
2014
2015 static guint32
2016 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2017 {
2018         MONO_REQ_GC_UNSAFE_MODE;
2019
2020         char *str;
2021         SigBuffer buf;
2022         guint32 idx, len;
2023
2024         sigbuffer_init (&buf, 32);
2025
2026         sigbuffer_add_value (&buf, minfo->type);
2027
2028         switch (minfo->type) {
2029         case MONO_NATIVE_BYVALTSTR:
2030         case MONO_NATIVE_BYVALARRAY:
2031                 sigbuffer_add_value (&buf, minfo->count);
2032                 break;
2033         case MONO_NATIVE_LPARRAY:
2034                 if (minfo->eltype || minfo->has_size) {
2035                         sigbuffer_add_value (&buf, minfo->eltype);
2036                         if (minfo->has_size) {
2037                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2038                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2039
2040                                 /* LAMESPEC: ElemMult is undocumented */
2041                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2042                         }
2043                 }
2044                 break;
2045         case MONO_NATIVE_SAFEARRAY:
2046                 if (minfo->eltype)
2047                         sigbuffer_add_value (&buf, minfo->eltype);
2048                 break;
2049         case MONO_NATIVE_CUSTOM:
2050                 if (minfo->guid) {
2051                         str = mono_string_to_utf8 (minfo->guid);
2052                         len = strlen (str);
2053                         sigbuffer_add_value (&buf, len);
2054                         sigbuffer_add_mem (&buf, str, len);
2055                         g_free (str);
2056                 } else {
2057                         sigbuffer_add_value (&buf, 0);
2058                 }
2059                 /* native type name */
2060                 sigbuffer_add_value (&buf, 0);
2061                 /* custom marshaler type name */
2062                 if (minfo->marshaltype || minfo->marshaltyperef) {
2063                         if (minfo->marshaltyperef)
2064                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2065                         else
2066                                 str = mono_string_to_utf8 (minfo->marshaltype);
2067                         len = strlen (str);
2068                         sigbuffer_add_value (&buf, len);
2069                         sigbuffer_add_mem (&buf, str, len);
2070                         g_free (str);
2071                 } else {
2072                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2073                         sigbuffer_add_value (&buf, 0);
2074                 }
2075                 if (minfo->mcookie) {
2076                         str = mono_string_to_utf8 (minfo->mcookie);
2077                         len = strlen (str);
2078                         sigbuffer_add_value (&buf, len);
2079                         sigbuffer_add_mem (&buf, str, len);
2080                         g_free (str);
2081                 } else {
2082                         sigbuffer_add_value (&buf, 0);
2083                 }
2084                 break;
2085         default:
2086                 break;
2087         }
2088         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089         sigbuffer_free (&buf);
2090         return idx;
2091 }
2092
2093 static void
2094 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2095 {
2096         MONO_REQ_GC_UNSAFE_MODE;
2097
2098         MonoDynamicTable *table;
2099         guint32 *values;
2100
2101         /* maybe this fixup should be done in the C# code */
2102         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2103                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2104         table = &assembly->tables [MONO_TABLE_FIELD];
2105         fb->table_idx = table->next_idx ++;
2106         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2107         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2108         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2109         values [MONO_FIELD_FLAGS] = fb->attrs;
2110         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2111
2112         if (fb->offset != -1) {
2113                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2114                 table->rows ++;
2115                 alloc_table (table, table->rows);
2116                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2117                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2118                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2119         }
2120         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2121                 guint32 field_type = 0;
2122                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2123                 table->rows ++;
2124                 alloc_table (table, table->rows);
2125                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2126                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2127                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2128                 values [MONO_CONSTANT_TYPE] = field_type;
2129                 values [MONO_CONSTANT_PADDING] = 0;
2130         }
2131         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2132                 guint32 rva_idx;
2133                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2134                 table->rows ++;
2135                 alloc_table (table, table->rows);
2136                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2137                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2138                 /*
2139                  * We store it in the code section because it's simpler for now.
2140                  */
2141                 if (fb->rva_data) {
2142                         if (mono_array_length (fb->rva_data) >= 10)
2143                                 stream_data_align (&assembly->code);
2144                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2145                 } else
2146                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2147                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2148         }
2149         if (fb->marshal_info) {
2150                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2151                 table->rows ++;
2152                 alloc_table (table, table->rows);
2153                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2154                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2155                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2156         }
2157 }
2158
2159 static guint32
2160 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2161 {
2162         MONO_REQ_GC_UNSAFE_MODE;
2163
2164         SigBuffer buf;
2165         guint32 nparams = 0;
2166         MonoReflectionMethodBuilder *mb = fb->get_method;
2167         MonoReflectionMethodBuilder *smb = fb->set_method;
2168         guint32 idx, i;
2169
2170         if (mb && mb->parameters)
2171                 nparams = mono_array_length (mb->parameters);
2172         if (!mb && smb && smb->parameters)
2173                 nparams = mono_array_length (smb->parameters) - 1;
2174         sigbuffer_init (&buf, 32);
2175         if (fb->call_conv & 0x20)
2176                 sigbuffer_add_byte (&buf, 0x28);
2177         else
2178                 sigbuffer_add_byte (&buf, 0x08);
2179         sigbuffer_add_value (&buf, nparams);
2180         if (mb) {
2181                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2182                 for (i = 0; i < nparams; ++i) {
2183                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2184                         encode_reflection_type (assembly, pt, &buf);
2185                 }
2186         } else if (smb && smb->parameters) {
2187                 /* the property type is the last param */
2188                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2189                 for (i = 0; i < nparams; ++i) {
2190                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2191                         encode_reflection_type (assembly, pt, &buf);
2192                 }
2193         } else {
2194                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2195         }
2196
2197         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2198         sigbuffer_free (&buf);
2199         return idx;
2200 }
2201
2202 static void
2203 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2204 {
2205         MONO_REQ_GC_UNSAFE_MODE;
2206
2207         MonoDynamicTable *table;
2208         guint32 *values;
2209         guint num_methods = 0;
2210         guint32 semaidx;
2211
2212         /* 
2213          * we need to set things in the following tables:
2214          * PROPERTYMAP (info already filled in _get_type_info ())
2215          * PROPERTY    (rows already preallocated in _get_type_info ())
2216          * METHOD      (method info already done with the generic method code)
2217          * METHODSEMANTICS
2218          * CONSTANT
2219          */
2220         table = &assembly->tables [MONO_TABLE_PROPERTY];
2221         pb->table_idx = table->next_idx ++;
2222         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2223         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2224         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2225         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2226
2227         /* FIXME: we still don't handle 'other' methods */
2228         if (pb->get_method) num_methods ++;
2229         if (pb->set_method) num_methods ++;
2230
2231         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2232         table->rows += num_methods;
2233         alloc_table (table, table->rows);
2234
2235         if (pb->get_method) {
2236                 semaidx = table->next_idx ++;
2237                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2238                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2239                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2240                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2241         }
2242         if (pb->set_method) {
2243                 semaidx = table->next_idx ++;
2244                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2245                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2246                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2247                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2248         }
2249         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2250                 guint32 field_type = 0;
2251                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2252                 table->rows ++;
2253                 alloc_table (table, table->rows);
2254                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2255                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2256                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2257                 values [MONO_CONSTANT_TYPE] = field_type;
2258                 values [MONO_CONSTANT_PADDING] = 0;
2259         }
2260 }
2261
2262 static void
2263 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2264 {
2265         MONO_REQ_GC_UNSAFE_MODE;
2266
2267         MonoDynamicTable *table;
2268         guint32 *values;
2269         guint num_methods = 0;
2270         guint32 semaidx;
2271
2272         /* 
2273          * we need to set things in the following tables:
2274          * EVENTMAP (info already filled in _get_type_info ())
2275          * EVENT    (rows already preallocated in _get_type_info ())
2276          * METHOD      (method info already done with the generic method code)
2277          * METHODSEMANTICS
2278          */
2279         table = &assembly->tables [MONO_TABLE_EVENT];
2280         eb->table_idx = table->next_idx ++;
2281         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2282         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2283         values [MONO_EVENT_FLAGS] = eb->attrs;
2284         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2285
2286         /*
2287          * FIXME: we still don't handle 'other' methods 
2288          */
2289         if (eb->add_method) num_methods ++;
2290         if (eb->remove_method) num_methods ++;
2291         if (eb->raise_method) num_methods ++;
2292
2293         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2294         table->rows += num_methods;
2295         alloc_table (table, table->rows);
2296
2297         if (eb->add_method) {
2298                 semaidx = table->next_idx ++;
2299                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2300                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2301                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2302                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2303         }
2304         if (eb->remove_method) {
2305                 semaidx = table->next_idx ++;
2306                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2307                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2308                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2309                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2310         }
2311         if (eb->raise_method) {
2312                 semaidx = table->next_idx ++;
2313                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2314                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2315                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2316                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2317         }
2318 }
2319
2320 static void
2321 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2322 {
2323         MONO_REQ_GC_UNSAFE_MODE;
2324
2325         MonoDynamicTable *table;
2326         guint32 num_constraints, i;
2327         guint32 *values;
2328         guint32 table_idx;
2329
2330         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2331         num_constraints = gparam->iface_constraints ?
2332                 mono_array_length (gparam->iface_constraints) : 0;
2333         table->rows += num_constraints;
2334         if (gparam->base_type)
2335                 table->rows++;
2336         alloc_table (table, table->rows);
2337
2338         if (gparam->base_type) {
2339                 table_idx = table->next_idx ++;
2340                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2341
2342                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2343                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2344                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2345         }
2346
2347         for (i = 0; i < num_constraints; i++) {
2348                 MonoReflectionType *constraint = mono_array_get (
2349                         gparam->iface_constraints, gpointer, i);
2350
2351                 table_idx = table->next_idx ++;
2352                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2353
2354                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2355                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2356                         assembly, mono_reflection_type_get_handle (constraint));
2357         }
2358 }
2359
2360 static void
2361 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2362 {
2363         MONO_REQ_GC_UNSAFE_MODE;
2364
2365         GenericParamTableEntry *entry;
2366
2367         /*
2368          * The GenericParam table must be sorted according to the `owner' field.
2369          * We need to do this sorting prior to writing the GenericParamConstraint
2370          * table, since we have to use the final GenericParam table indices there
2371          * and they must also be sorted.
2372          */
2373
2374         entry = g_new0 (GenericParamTableEntry, 1);
2375         entry->owner = owner;
2376         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2377         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2378         entry->gparam = gparam;
2379         
2380         g_ptr_array_add (assembly->gen_params, entry);
2381 }
2382
2383 static void
2384 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2385 {
2386         MONO_REQ_GC_UNSAFE_MODE;
2387
2388         MonoDynamicTable *table;
2389         MonoGenericParam *param;
2390         guint32 *values;
2391         guint32 table_idx;
2392
2393         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2394         table_idx = table->next_idx ++;
2395         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2396
2397         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2398
2399         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2400         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2401         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2402         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2403
2404         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2405
2406         encode_constraints (entry->gparam, table_idx, assembly);
2407 }
2408
2409 static guint32
2410 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2411 {
2412         MONO_REQ_GC_UNSAFE_MODE;
2413
2414         MonoDynamicTable *table;
2415         guint32 token;
2416         guint32 *values;
2417         guint32 cols [MONO_ASSEMBLY_SIZE];
2418         const char *pubkey;
2419         guint32 publen;
2420
2421         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2422                 return token;
2423
2424         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2425                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2426                 token = table->next_idx ++;
2427                 table->rows ++;
2428                 alloc_table (table, table->rows);
2429                 values = table->values + token * MONO_MODULEREF_SIZE;
2430                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2431
2432                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2433                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2434                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2435
2436                 return token;
2437         }
2438         
2439         if (assembly_is_dynamic (image->assembly))
2440                 /* FIXME: */
2441                 memset (cols, 0, sizeof (cols));
2442         else {
2443                 /* image->assembly->image is the manifest module */
2444                 image = image->assembly->image;
2445                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2446         }
2447
2448         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2449         token = table->next_idx ++;
2450         table->rows ++;
2451         alloc_table (table, table->rows);
2452         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2453         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2454         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2455         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2456         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2457         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2458         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2459         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2460         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2461
2462         if (strcmp ("", image->assembly->aname.culture)) {
2463                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2464                                 image->assembly->aname.culture);
2465         }
2466
2467         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2468                 guchar pubtoken [9];
2469                 pubtoken [0] = 8;
2470                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2471                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2472         } else {
2473                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2474         }
2475         token <<= MONO_RESOLUTION_SCOPE_BITS;
2476         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2477         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2478         return token;
2479 }
2480
2481 static guint32
2482 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2483 {
2484         MONO_REQ_GC_NEUTRAL_MODE;
2485
2486         MonoDynamicTable *table;
2487         guint32 *values;
2488         guint32 token;
2489         SigBuffer buf;
2490
2491         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2492                 return token;
2493
2494         sigbuffer_init (&buf, 32);
2495         switch (type->type) {
2496         case MONO_TYPE_FNPTR:
2497         case MONO_TYPE_PTR:
2498         case MONO_TYPE_SZARRAY:
2499         case MONO_TYPE_ARRAY:
2500         case MONO_TYPE_VAR:
2501         case MONO_TYPE_MVAR:
2502         case MONO_TYPE_GENERICINST:
2503                 encode_type (assembly, type, &buf);
2504                 break;
2505         case MONO_TYPE_CLASS:
2506         case MONO_TYPE_VALUETYPE: {
2507                 MonoClass *k = mono_class_from_mono_type (type);
2508                 if (!k || !k->generic_container) {
2509                         sigbuffer_free (&buf);
2510                         return 0;
2511                 }
2512                 encode_type (assembly, type, &buf);
2513                 break;
2514         }
2515         default:
2516                 sigbuffer_free (&buf);
2517                 return 0;
2518         }
2519
2520         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2521         if (assembly->save) {
2522                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2523                 alloc_table (table, table->rows + 1);
2524                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2525                 values [MONO_TYPESPEC_SIGNATURE] = token;
2526         }
2527         sigbuffer_free (&buf);
2528
2529         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2530         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2531         table->next_idx ++;
2532         return token;
2533 }
2534
2535 static guint32
2536 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2537 {
2538         MONO_REQ_GC_UNSAFE_MODE;
2539
2540         MonoDynamicTable *table;
2541         guint32 *values;
2542         guint32 token, scope, enclosing;
2543         MonoClass *klass;
2544
2545         /* if the type requires a typespec, we must try that first*/
2546         if (try_typespec && (token = create_typespec (assembly, type)))
2547                 return token;
2548         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2549         if (token)
2550                 return token;
2551         klass = mono_class_from_mono_type (type);
2552         if (!klass)
2553                 klass = mono_class_from_mono_type (type);
2554
2555         /*
2556          * If it's in the same module and not a generic type parameter:
2557          */
2558         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2559                         (type->type != MONO_TYPE_MVAR)) {
2560                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2561                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2562                 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2563                 return token;
2564         }
2565
2566         if (klass->nested_in) {
2567                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2568                 /* get the typeref idx of the enclosing type */
2569                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2570                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2571         } else {
2572                 scope = resolution_scope_from_image (assembly, klass->image);
2573         }
2574         table = &assembly->tables [MONO_TABLE_TYPEREF];
2575         if (assembly->save) {
2576                 alloc_table (table, table->rows + 1);
2577                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2578                 values [MONO_TYPEREF_SCOPE] = scope;
2579                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2580                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2581         }
2582         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2583         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2584         table->next_idx ++;
2585         register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2586         return token;
2587 }
2588
2589 /*
2590  * Despite the name, we handle also TypeSpec (with the above helper).
2591  */
2592 static guint32
2593 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2594 {
2595         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2596 }
2597
2598 #ifndef DISABLE_REFLECTION_EMIT
2599 static guint32
2600 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2601 {
2602         MONO_REQ_GC_NEUTRAL_MODE;
2603
2604         MonoDynamicTable *table;
2605         guint32 *values;
2606         guint32 token, pclass;
2607
2608         switch (parent & MONO_TYPEDEFORREF_MASK) {
2609         case MONO_TYPEDEFORREF_TYPEREF:
2610                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2611                 break;
2612         case MONO_TYPEDEFORREF_TYPESPEC:
2613                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2614                 break;
2615         case MONO_TYPEDEFORREF_TYPEDEF:
2616                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2617                 break;
2618         default:
2619                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2620                 return 0;
2621         }
2622         /* extract the index */
2623         parent >>= MONO_TYPEDEFORREF_BITS;
2624
2625         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2626
2627         if (assembly->save) {
2628                 alloc_table (table, table->rows + 1);
2629                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2630                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2631                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2632                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2633         }
2634
2635         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2636         table->next_idx ++;
2637
2638         return token;
2639 }
2640
2641 /*
2642  * Insert a memberef row into the metadata: the token that point to the memberref
2643  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2644  * mono_image_get_fieldref_token()).
2645  * The sig param is an index to an already built signature.
2646  */
2647 static guint32
2648 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2649 {
2650         MONO_REQ_GC_NEUTRAL_MODE;
2651
2652         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2653         return mono_image_add_memberef_row (assembly, parent, name, sig);
2654 }
2655
2656
2657 static guint32
2658 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2659 {
2660         MONO_REQ_GC_NEUTRAL_MODE;
2661
2662         guint32 token;
2663         MonoMethodSignature *sig;
2664         
2665         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2666
2667         if (create_typespec) {
2668                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2669                 if (token)
2670                         return token;
2671         } 
2672
2673         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2674         if (token && !create_typespec)
2675                 return token;
2676
2677         g_assert (!method->is_inflated);
2678         if (!token) {
2679                 /*
2680                  * A methodref signature can't contain an unmanaged calling convention.
2681                  */
2682                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2683                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2684                         sig->call_convention = MONO_CALL_DEFAULT;
2685                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2686                         method->name,  method_encode_signature (assembly, sig));
2687                 g_free (sig);
2688                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2689         }
2690
2691         if (create_typespec) {
2692                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2693                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2694                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2695
2696                 if (assembly->save) {
2697                         guint32 *values;
2698
2699                         alloc_table (table, table->rows + 1);
2700                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2701                         values [MONO_METHODSPEC_METHOD] = token;
2702                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2703                 }
2704
2705                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2706                 table->next_idx ++;
2707                 /*methodspec and memberef tokens are diferent, */
2708                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2709                 return token;
2710         }
2711         return token;
2712 }
2713
2714 static guint32
2715 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2716 {
2717         guint32 token, parent, sig;
2718         ReflectionMethodBuilder rmb;
2719         char *name;
2720         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2721         
2722         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2723         if (token)
2724                 return token;
2725
2726         name = mono_string_to_utf8 (method->name);
2727         reflection_methodbuilder_from_method_builder (&rmb, method);
2728
2729         /*
2730          * A methodref signature can't contain an unmanaged calling convention.
2731          * Since some flags are encoded as part of call_conv, we need to check against it.
2732         */
2733         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2734                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2735
2736         sig = method_builder_encode_signature (assembly, &rmb);
2737
2738         if (tb->generic_params)
2739                 parent = create_generic_typespec (assembly, tb);
2740         else
2741                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2742
2743         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2744
2745         g_free (name);
2746         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2747         return token;
2748 }
2749
2750 static guint32
2751 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2752                                      const gchar *name, guint32 sig)
2753 {
2754         MonoDynamicTable *table;
2755         guint32 token;
2756         guint32 *values;
2757         
2758         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2759
2760         if (assembly->save) {
2761                 alloc_table (table, table->rows + 1);
2762                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2763                 values [MONO_MEMBERREF_CLASS] = original;
2764                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2765                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2766         }
2767
2768         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2769         table->next_idx ++;
2770
2771         return token;
2772 }
2773
2774 static guint32
2775 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2776 {
2777         SigBuffer buf;
2778         int i;
2779         guint32 nparams = mono_array_length (mb->generic_params);
2780         guint32 idx;
2781
2782         if (!assembly->save)
2783                 return 0;
2784
2785         sigbuffer_init (&buf, 32);
2786
2787         sigbuffer_add_value (&buf, 0xa);
2788         sigbuffer_add_value (&buf, nparams);
2789
2790         for (i = 0; i < nparams; i++) {
2791                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2792                 sigbuffer_add_value (&buf, i);
2793         }
2794
2795         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2796         sigbuffer_free (&buf);
2797         return idx;
2798 }
2799
2800 static guint32
2801 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2802 {
2803         MonoDynamicTable *table;
2804         guint32 *values;
2805         guint32 token, mtoken = 0;
2806
2807         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2808         if (token)
2809                 return token;
2810
2811         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2812
2813         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2814         switch (mono_metadata_token_table (mtoken)) {
2815         case MONO_TABLE_MEMBERREF:
2816                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2817                 break;
2818         case MONO_TABLE_METHOD:
2819                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2820                 break;
2821         default:
2822                 g_assert_not_reached ();
2823         }
2824
2825         if (assembly->save) {
2826                 alloc_table (table, table->rows + 1);
2827                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2828                 values [MONO_METHODSPEC_METHOD] = mtoken;
2829                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2830         }
2831
2832         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2833         table->next_idx ++;
2834
2835         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2836         return token;
2837 }
2838
2839 static guint32
2840 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2841 {
2842         guint32 token;
2843
2844         if (mb->generic_params && create_methodspec) 
2845                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2846
2847         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2848         if (token)
2849                 return token;
2850
2851         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2852         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2853         return token;
2854 }
2855
2856 static guint32
2857 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2858 {
2859         guint32 token, parent, sig;
2860         ReflectionMethodBuilder rmb;
2861         char *name;
2862         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2863         
2864         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2865         if (token)
2866                 return token;
2867
2868         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2869
2870         if (tb->generic_params)
2871                 parent = create_generic_typespec (assembly, tb);
2872         else
2873                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2874         
2875         name = mono_string_to_utf8 (rmb.name);
2876         sig = method_builder_encode_signature (assembly, &rmb);
2877
2878         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2879
2880         g_free (name);
2881         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2882         return token;
2883 }
2884 #endif
2885
2886 static gboolean
2887 is_field_on_inst (MonoClassField *field)
2888 {
2889         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2890 }
2891
2892 /*
2893  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2894  */
2895 static MonoType*
2896 get_field_on_inst_generic_type (MonoClassField *field)
2897 {
2898         MonoClass *klass, *gtd;
2899         MonoDynamicGenericClass *dgclass;
2900         int field_index;
2901
2902         g_assert (is_field_on_inst (field));
2903
2904         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2905
2906         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2907                 field_index = field - dgclass->fields;
2908                 return dgclass->field_generic_types [field_index];              
2909         }
2910
2911         klass = field->parent;
2912         gtd = klass->generic_class->container_class;
2913
2914         if (field >= klass->fields && field - klass->fields < klass->field.count) {
2915                 field_index = field - klass->fields;
2916                 return gtd->fields [field_index].type;
2917         }
2918
2919         g_assert_not_reached ();
2920         return 0;
2921 }
2922
2923 #ifndef DISABLE_REFLECTION_EMIT
2924 static guint32
2925 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2926 {
2927         MonoType *type;
2928         guint32 token;
2929
2930         g_assert (field);
2931         g_assert (field->parent);
2932
2933         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2934         if (token)
2935                 return token;
2936
2937         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2938                 int index = field - field->parent->fields;
2939                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2940         } else {
2941                 if (is_field_on_inst (field))
2942                         type = get_field_on_inst_generic_type (field);
2943                 else
2944                         type = mono_field_get_type (field);
2945         }
2946         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2947                                                                                         mono_field_get_name (field),
2948                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2949         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2950         return token;
2951 }
2952
2953 static guint32
2954 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2955 {
2956         guint32 token;
2957         MonoClass *klass;
2958         MonoGenericClass *gclass;
2959         MonoType *type;
2960         char *name;
2961
2962         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2963         if (token)
2964                 return token;
2965         if (is_sre_field_builder (mono_object_class (f->fb))) {
2966                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2967                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2968                 klass = mono_class_from_mono_type (type);
2969                 gclass = type->data.generic_class;
2970                 g_assert (gclass->is_dynamic);
2971
2972                 name = mono_string_to_utf8 (fb->name);
2973                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2974                                                                                                 field_encode_signature (assembly, fb));
2975                 g_free (name);          
2976         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2977                 guint32 sig;
2978                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2979
2980                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2981                 klass = mono_class_from_mono_type (type);
2982
2983                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2984                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2985         } else {
2986                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2987                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2988         }
2989
2990         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2991         return token;
2992 }
2993
2994 static guint32
2995 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2996 {
2997         guint32 sig, token;
2998         MonoClass *klass;
2999         MonoGenericClass *gclass;
3000         MonoType *type;
3001
3002         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3003
3004         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3005         if (token)
3006                 return token;
3007
3008         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3009                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3010                 ReflectionMethodBuilder rmb;
3011                 char *name;
3012
3013                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3014                 klass = mono_class_from_mono_type (type);
3015
3016                 gclass = type->data.generic_class;
3017                 g_assert (gclass->is_dynamic);
3018
3019                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3020
3021                 name = mono_string_to_utf8 (rmb.name);
3022
3023                 sig = method_builder_encode_signature (assembly, &rmb);
3024
3025                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3026                 g_free (name);
3027         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3028                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3029
3030                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3031                 klass = mono_class_from_mono_type (type);
3032
3033                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3034                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3035         } else {
3036                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3037                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3038         }
3039
3040
3041         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3042         return token;
3043 }
3044
3045 static MonoMethod*
3046 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3047 {
3048         MonoError error;
3049         MonoClass *klass;
3050         MonoGenericContext tmp_context;
3051         MonoType **type_argv;
3052         MonoGenericInst *ginst;
3053         MonoMethod *method, *inflated;
3054         int count, i;
3055
3056         init_type_builder_generics ((MonoObject*)m->inst);
3057
3058         method = inflate_method (m->inst, (MonoObject*)m->mb);
3059
3060         klass = method->klass;
3061
3062         if (m->method_args == NULL)
3063                 return method;
3064
3065         if (method->is_inflated)
3066                 method = ((MonoMethodInflated *) method)->declaring;
3067
3068         count = mono_array_length (m->method_args);
3069
3070         type_argv = g_new0 (MonoType *, count);
3071         for (i = 0; i < count; i++) {
3072                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
3073                 type_argv [i] = mono_reflection_type_get_handle (garg);
3074         }
3075         ginst = mono_metadata_get_generic_inst (count, type_argv);
3076         g_free (type_argv);
3077
3078         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3079         tmp_context.method_inst = ginst;
3080
3081         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3082         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3083         return inflated;
3084 }
3085
3086 static guint32
3087 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3088 {
3089         guint32 sig, token = 0;
3090         MonoType *type;
3091         MonoClass *klass;
3092
3093         if (m->method_args) {
3094                 MonoMethod *inflated;
3095
3096                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3097                 if (create_methodspec)
3098                         token = mono_image_get_methodspec_token (assembly, inflated);
3099                 else
3100                         token = mono_image_get_inflated_method_token (assembly, inflated);
3101                 return token;
3102         }
3103
3104         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3105         if (token)
3106                 return token;
3107
3108         if (is_sre_method_builder (mono_object_class (m->mb))) {
3109                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3110                 MonoGenericClass *gclass;
3111                 ReflectionMethodBuilder rmb;
3112                 char *name;
3113
3114                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3115                 klass = mono_class_from_mono_type (type);
3116                 gclass = type->data.generic_class;
3117                 g_assert (gclass->is_dynamic);
3118
3119                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3120
3121                 name = mono_string_to_utf8 (rmb.name);
3122
3123                 sig = method_builder_encode_signature (assembly, &rmb);
3124
3125                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3126                 g_free (name);          
3127         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3128                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3129
3130                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3131                 klass = mono_class_from_mono_type (type);
3132
3133                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3134                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3135         } else {
3136                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3137                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3138         }
3139
3140         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3141         return token;
3142 }
3143
3144 static guint32
3145 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3146 {
3147         SigBuffer buf;
3148         int i;
3149         guint32 nparams = context->method_inst->type_argc;
3150         guint32 idx;
3151
3152         if (!assembly->save)
3153                 return 0;
3154
3155         sigbuffer_init (&buf, 32);
3156         /*
3157          * FIXME: vararg, explicit_this, differenc call_conv values...
3158          */
3159         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3160         sigbuffer_add_value (&buf, nparams);
3161
3162         for (i = 0; i < nparams; i++)
3163                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3164
3165         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3166         sigbuffer_free (&buf);
3167         return idx;
3168 }
3169
3170 static guint32
3171 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3172 {
3173         MonoDynamicTable *table;
3174         guint32 *values;
3175         guint32 token, mtoken = 0, sig;
3176         MonoMethodInflated *imethod;
3177         MonoMethod *declaring;
3178
3179         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3180
3181         g_assert (method->is_inflated);
3182         imethod = (MonoMethodInflated *) method;
3183         declaring = imethod->declaring;
3184
3185         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3186         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3187
3188         if (!mono_method_signature (declaring)->generic_param_count)
3189                 return mtoken;
3190
3191         switch (mono_metadata_token_table (mtoken)) {
3192         case MONO_TABLE_MEMBERREF:
3193                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3194                 break;
3195         case MONO_TABLE_METHOD:
3196                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3197                 break;
3198         default:
3199                 g_assert_not_reached ();
3200         }
3201
3202         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3203
3204         if (assembly->save) {
3205                 alloc_table (table, table->rows + 1);
3206                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3207                 values [MONO_METHODSPEC_METHOD] = mtoken;
3208                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3209         }
3210
3211         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3212         table->next_idx ++;
3213
3214         return token;
3215 }
3216
3217 static guint32
3218 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3219 {
3220         MonoMethodInflated *imethod;
3221         guint32 token;
3222         
3223         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3224         if (token)
3225                 return token;
3226
3227         g_assert (method->is_inflated);
3228         imethod = (MonoMethodInflated *) method;
3229
3230         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3231                 token = method_encode_methodspec (assembly, method);
3232         } else {
3233                 guint32 sig = method_encode_signature (
3234                         assembly, mono_method_signature (imethod->declaring));
3235                 token = mono_image_get_memberref_token (
3236                         assembly, &method->klass->byval_arg, method->name, sig);
3237         }
3238
3239         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3240         return token;
3241 }
3242
3243 static guint32
3244 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3245 {
3246         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3247         guint32 sig, token;
3248
3249         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3250         token = mono_image_get_memberref_token (
3251                 assembly, &m->klass->byval_arg, m->name, sig);
3252
3253         return token;
3254 }
3255
3256 static guint32
3257 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3258 {
3259         MonoDynamicTable *table;
3260         MonoClass *klass;
3261         MonoType *type;
3262         guint32 *values;
3263         guint32 token;
3264         SigBuffer buf;
3265         int count, i;
3266
3267         /*
3268          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3269          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3270          * Because of this, we must not insert it into the `typeref' hash table.
3271          */
3272         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3273         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3274         if (token)
3275                 return token;
3276
3277         sigbuffer_init (&buf, 32);
3278
3279         g_assert (tb->generic_params);
3280         klass = mono_class_from_mono_type (type);
3281
3282         if (tb->generic_container)
3283                 mono_reflection_create_generic_class (tb);
3284
3285         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3286         g_assert (klass->generic_container);
3287         sigbuffer_add_value (&buf, klass->byval_arg.type);
3288         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3289
3290         count = mono_array_length (tb->generic_params);
3291         sigbuffer_add_value (&buf, count);
3292         for (i = 0; i < count; i++) {
3293                 MonoReflectionGenericParam *gparam;
3294
3295                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3296
3297                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3298         }
3299
3300         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3301
3302         if (assembly->save) {
3303                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3304                 alloc_table (table, table->rows + 1);
3305                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3306                 values [MONO_TYPESPEC_SIGNATURE] = token;
3307         }
3308         sigbuffer_free (&buf);
3309
3310         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3311         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3312         table->next_idx ++;
3313         return token;
3314 }
3315
3316 /*
3317  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3318  */
3319 static MonoType*
3320 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3321 {
3322         int i, count, len, pos;
3323         MonoType *t;
3324
3325         count = 0;
3326         if (modreq)
3327                 count += mono_array_length (modreq);
3328         if (modopt)
3329                 count += mono_array_length (modopt);
3330
3331         if (count == 0)
3332                 return mono_metadata_type_dup (NULL, type);
3333
3334         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3335         t = g_malloc (len);
3336         memcpy (t, type, MONO_SIZEOF_TYPE);
3337
3338         t->num_mods = count;
3339         pos = 0;
3340         if (modreq) {
3341                 for (i = 0; i < mono_array_length (modreq); ++i) {
3342                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3343                         t->modifiers [pos].required = 1;
3344                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3345                         pos ++;
3346                 }
3347         }
3348         if (modopt) {
3349                 for (i = 0; i < mono_array_length (modopt); ++i) {
3350                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3351                         t->modifiers [pos].required = 0;
3352                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3353                         pos ++;
3354                 }
3355         }
3356
3357         return t;
3358 }
3359
3360 static void
3361 init_type_builder_generics (MonoObject *type)
3362 {
3363         MonoReflectionTypeBuilder *tb;
3364
3365         if (!is_sre_type_builder(mono_object_class (type)))
3366                 return;
3367         tb = (MonoReflectionTypeBuilder *)type;
3368
3369         if (tb && tb->generic_container)
3370                 mono_reflection_create_generic_class (tb);
3371 }
3372
3373 static guint32
3374 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3375 {
3376         MonoDynamicTable *table;
3377         MonoType *custom = NULL, *type;
3378         guint32 *values;
3379         guint32 token, pclass, parent, sig;
3380         gchar *name;
3381
3382         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3383         if (token)
3384                 return token;
3385
3386         /* FIXME: is this call necessary? */
3387         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3388         name = mono_string_to_utf8 (fb->name);
3389
3390         /*FIXME this is one more layer of ugliness due how types are created.*/
3391         init_type_builder_generics (fb->type);
3392
3393         /* fb->type does not include the custom modifiers */
3394         /* FIXME: We should do this in one place when a fieldbuilder is created */
3395         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3396         if (fb->modreq || fb->modopt)
3397                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3398
3399         sig = fieldref_encode_signature (assembly, NULL, type);
3400         g_free (custom);
3401
3402         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3403         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3404         
3405         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3406         parent >>= MONO_TYPEDEFORREF_BITS;
3407
3408         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3409
3410         if (assembly->save) {
3411                 alloc_table (table, table->rows + 1);
3412                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3413                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3414                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3415                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3416         }
3417
3418         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3419         table->next_idx ++;
3420         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3421         g_free (name);
3422         return token;
3423 }
3424
3425 static guint32
3426 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3427 {
3428         SigBuffer buf;
3429         guint32 nargs;
3430         guint32 i, idx;
3431
3432         if (!assembly->save)
3433                 return 0;
3434
3435         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3436         g_assert (helper->type == 2);
3437
3438         if (helper->arguments)
3439                 nargs = mono_array_length (helper->arguments);
3440         else
3441                 nargs = 0;
3442
3443         sigbuffer_init (&buf, 32);
3444
3445         /* Encode calling convention */
3446         /* Change Any to Standard */
3447         if ((helper->call_conv & 0x03) == 0x03)
3448                 helper->call_conv = 0x01;
3449         /* explicit_this implies has_this */
3450         if (helper->call_conv & 0x40)
3451                 helper->call_conv &= 0x20;
3452
3453         if (helper->call_conv == 0) { /* Unmanaged */
3454                 idx = helper->unmanaged_call_conv - 1;
3455         } else {
3456                 /* Managed */
3457                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3458                 if (helper->call_conv & 0x02) /* varargs */
3459                         idx += 0x05;
3460         }
3461
3462         sigbuffer_add_byte (&buf, idx);
3463         sigbuffer_add_value (&buf, nargs);
3464         encode_reflection_type (assembly, helper->return_type, &buf);
3465         for (i = 0; i < nargs; ++i) {
3466                 MonoArray *modreqs = NULL;
3467                 MonoArray *modopts = NULL;
3468                 MonoReflectionType *pt;
3469
3470                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3471                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3472                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3473                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3474
3475                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3476                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3477                 encode_reflection_type (assembly, pt, &buf);
3478         }
3479         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3480         sigbuffer_free (&buf);
3481
3482         return idx;
3483 }
3484
3485 static guint32 
3486 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3487 {
3488         guint32 idx;
3489         MonoDynamicTable *table;
3490         guint32 *values;
3491
3492         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3493         idx = table->next_idx ++;
3494         table->rows ++;
3495         alloc_table (table, table->rows);
3496         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3497
3498         values [MONO_STAND_ALONE_SIGNATURE] =
3499                 mono_reflection_encode_sighelper (assembly, helper);
3500
3501         return idx;
3502 }
3503
3504 static int
3505 reflection_cc_to_file (int call_conv) {
3506         switch (call_conv & 0x3) {
3507         case 0:
3508         case 1: return MONO_CALL_DEFAULT;
3509         case 2: return MONO_CALL_VARARG;
3510         default:
3511                 g_assert_not_reached ();
3512         }
3513         return 0;
3514 }
3515 #endif /* !DISABLE_REFLECTION_EMIT */
3516
3517 typedef struct {
3518         MonoType *parent;
3519         MonoMethodSignature *sig;
3520         char *name;
3521         guint32 token;
3522 } ArrayMethod;
3523
3524 #ifndef DISABLE_REFLECTION_EMIT
3525 static guint32
3526 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3527 {
3528         guint32 nparams, i;
3529         GList *tmp;
3530         char *name;
3531         MonoMethodSignature *sig;
3532         ArrayMethod *am;
3533         MonoType *mtype;
3534
3535         name = mono_string_to_utf8 (m->name);
3536         nparams = mono_array_length (m->parameters);
3537         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3538         sig->hasthis = 1;
3539         sig->sentinelpos = -1;
3540         sig->call_convention = reflection_cc_to_file (m->call_conv);
3541         sig->param_count = nparams;
3542         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3543         mtype = mono_reflection_type_get_handle (m->parent);
3544         for (i = 0; i < nparams; ++i)
3545                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3546
3547         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3548                 am = tmp->data;
3549                 if (strcmp (name, am->name) == 0 && 
3550                                 mono_metadata_type_equal (am->parent, mtype) &&
3551                                 mono_metadata_signature_equal (am->sig, sig)) {
3552                         g_free (name);
3553                         g_free (sig);
3554                         m->table_idx = am->token & 0xffffff;
3555                         return am->token;
3556                 }
3557         }
3558         am = g_new0 (ArrayMethod, 1);
3559         am->name = name;
3560         am->sig = sig;
3561         am->parent = mtype;
3562         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3563                 method_encode_signature (assembly, sig));
3564         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3565         m->table_idx = am->token & 0xffffff;
3566         return am->token;
3567 }
3568
3569 /*
3570  * Insert into the metadata tables all the info about the TypeBuilder tb.
3571  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3572  */
3573 static void
3574 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3575 {
3576         MonoDynamicTable *table;
3577         guint *values;
3578         int i, is_object = 0, is_system = 0;
3579         char *n;
3580
3581         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3582         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3583         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3584         n = mono_string_to_utf8 (tb->name);
3585         if (strcmp (n, "Object") == 0)
3586                 is_object++;
3587         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3588         g_free (n);
3589         n = mono_string_to_utf8 (tb->nspace);
3590         if (strcmp (n, "System") == 0)
3591                 is_system++;
3592         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3593         g_free (n);
3594         if (tb->parent && !(is_system && is_object) && 
3595                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3596                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3597         } else {
3598                 values [MONO_TYPEDEF_EXTENDS] = 0;
3599         }
3600         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3601         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3602
3603         /*
3604          * if we have explicitlayout or sequentiallayouts, output data in the
3605          * ClassLayout table.
3606          */
3607         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3608                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3609                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3610                 table->rows++;
3611                 alloc_table (table, table->rows);
3612                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3613                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3614                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3615                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3616         }
3617
3618         /* handle interfaces */
3619         if (tb->interfaces) {
3620                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3621                 i = table->rows;
3622                 table->rows += mono_array_length (tb->interfaces);
3623                 alloc_table (table, table->rows);
3624                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3625                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3626                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3627                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3628                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3629                         values += MONO_INTERFACEIMPL_SIZE;
3630                 }
3631         }
3632
3633         /* handle fields */
3634         if (tb->fields) {
3635                 table = &assembly->tables [MONO_TABLE_FIELD];
3636                 table->rows += tb->num_fields;
3637                 alloc_table (table, table->rows);
3638                 for (i = 0; i < tb->num_fields; ++i)
3639                         mono_image_get_field_info (
3640                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3641         }
3642
3643         /* handle constructors */
3644         if (tb->ctors) {
3645                 table = &assembly->tables [MONO_TABLE_METHOD];
3646                 table->rows += mono_array_length (tb->ctors);
3647                 alloc_table (table, table->rows);
3648                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3649                         mono_image_get_ctor_info (domain,
3650                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3651         }
3652
3653         /* handle methods */
3654         if (tb->methods) {
3655                 table = &assembly->tables [MONO_TABLE_METHOD];
3656                 table->rows += tb->num_methods;
3657                 alloc_table (table, table->rows);
3658                 for (i = 0; i < tb->num_methods; ++i)
3659                         mono_image_get_method_info (
3660                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3661         }
3662
3663         /* Do the same with properties etc.. */
3664         if (tb->events && mono_array_length (tb->events)) {
3665                 table = &assembly->tables [MONO_TABLE_EVENT];
3666                 table->rows += mono_array_length (tb->events);
3667                 alloc_table (table, table->rows);
3668                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3669                 table->rows ++;
3670                 alloc_table (table, table->rows);
3671                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3672                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3673                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3674                 for (i = 0; i < mono_array_length (tb->events); ++i)
3675                         mono_image_get_event_info (
3676                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3677         }
3678         if (tb->properties && mono_array_length (tb->properties)) {
3679                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3680                 table->rows += mono_array_length (tb->properties);
3681                 alloc_table (table, table->rows);
3682                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3683                 table->rows ++;
3684                 alloc_table (table, table->rows);
3685                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3686                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3687                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3688                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3689                         mono_image_get_property_info (
3690                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3691         }
3692
3693         /* handle generic parameters */
3694         if (tb->generic_params) {
3695                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3696                 table->rows += mono_array_length (tb->generic_params);
3697                 alloc_table (table, table->rows);
3698                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3699                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3700
3701                         mono_image_get_generic_param_info (
3702                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3703                 }
3704         }
3705
3706         mono_image_add_decl_security (assembly, 
3707                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3708
3709         if (tb->subtypes) {
3710                 MonoDynamicTable *ntable;
3711                 
3712                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3713                 ntable->rows += mono_array_length (tb->subtypes);
3714                 alloc_table (ntable, ntable->rows);
3715                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3716
3717                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3718                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3719
3720                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3721                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3722                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3723                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3724                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3725                                 ntable->next_idx, ntable->rows);*/
3726                         values += MONO_NESTED_CLASS_SIZE;
3727                         ntable->next_idx++;
3728                 }
3729         }
3730 }
3731 #endif
3732
3733 static void
3734 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3735 {
3736         int i;
3737
3738         mono_ptr_array_append (*types, type);
3739
3740         if (!type->subtypes)
3741                 return;
3742
3743         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3744                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3745                 collect_types (types, subtype);
3746         }
3747 }
3748
3749 static gint
3750 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3751 {
3752         if ((*type1)->table_idx < (*type2)->table_idx)
3753                 return -1;
3754         else
3755                 if ((*type1)->table_idx > (*type2)->table_idx)
3756                         return 1;
3757         else
3758                 return 0;
3759 }
3760
3761 static void
3762 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3763         int i;
3764
3765         if (!pinfo)
3766                 return;
3767         for (i = 0; i < mono_array_length (pinfo); ++i) {
3768                 MonoReflectionParamBuilder *pb;
3769                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3770                 if (!pb)
3771                         continue;
3772                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3773         }
3774 }
3775
3776 static void
3777 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3778         int i;
3779         
3780         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3781         if (tb->fields) {
3782                 for (i = 0; i < tb->num_fields; ++i) {
3783                         MonoReflectionFieldBuilder* fb;
3784                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3785                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3786                 }
3787         }
3788         if (tb->events) {
3789                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3790                         MonoReflectionEventBuilder* eb;
3791                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3792                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3793                 }
3794         }
3795         if (tb->properties) {
3796                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3797                         MonoReflectionPropertyBuilder* pb;
3798                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3799                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3800                 }
3801         }
3802         if (tb->ctors) {
3803                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3804                         MonoReflectionCtorBuilder* cb;
3805                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3806                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3807                         params_add_cattrs (assembly, cb->pinfo);
3808                 }
3809         }
3810
3811         if (tb->methods) {
3812                 for (i = 0; i < tb->num_methods; ++i) {
3813                         MonoReflectionMethodBuilder* mb;
3814                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3815                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3816                         params_add_cattrs (assembly, mb->pinfo);
3817                 }
3818         }
3819
3820         if (tb->subtypes) {
3821                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3822                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3823         }
3824 }
3825
3826 static void
3827 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3828 {
3829         int i;
3830         
3831         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3832
3833         if (moduleb->global_methods) {
3834                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3835                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3836                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3837                         params_add_cattrs (assembly, mb->pinfo);
3838                 }
3839         }
3840
3841         if (moduleb->global_fields) {
3842                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3843                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3844                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3845                 }
3846         }
3847         
3848         if (moduleb->types) {
3849                 for (i = 0; i < moduleb->num_types; ++i)
3850                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3851         }
3852 }
3853
3854 static void
3855 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3856 {
3857         MonoDynamicTable *table;
3858         guint32 *values;
3859         char blob_size [6];
3860         guchar hash [20];
3861         char *b = blob_size;
3862         char *dir, *path;
3863
3864         table = &assembly->tables [MONO_TABLE_FILE];
3865         table->rows++;
3866         alloc_table (table, table->rows);
3867         values = table->values + table->next_idx * MONO_FILE_SIZE;
3868         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3869         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3870         if (image_is_dynamic (module->image)) {
3871                 /* This depends on the fact that the main module is emitted last */
3872                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3873                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3874         } else {
3875                 dir = NULL;
3876                 path = g_strdup (module->image->name);
3877         }
3878         mono_sha1_get_digest_from_file (path, hash);
3879         g_free (dir);
3880         g_free (path);
3881         mono_metadata_encode_value (20, b, &b);
3882         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3883         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3884         table->next_idx ++;
3885 }
3886
3887 static void
3888 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3889 {
3890         MonoDynamicTable *table;
3891         int i;
3892
3893         table = &assembly->tables [MONO_TABLE_MODULE];
3894         mb->table_idx = table->next_idx ++;
3895         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3896         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3897         i /= 16;
3898         ++i;
3899         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3900         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3901         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3902         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3903 }
3904
3905 static guint32
3906 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3907         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3908 {
3909         MonoDynamicTable *table;
3910         guint32 *values;
3911         guint32 visib, res;
3912
3913         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3914         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3915                 return 0;
3916
3917         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3918         table->rows++;
3919         alloc_table (table, table->rows);
3920         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3921
3922         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3923         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3924         if (klass->nested_in)
3925                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3926         else
3927                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3928         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3929         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3930
3931         res = table->next_idx;
3932
3933         table->next_idx ++;
3934
3935         /* Emit nested types */
3936         if (klass->ext && klass->ext->nested_classes) {
3937                 GList *tmp;
3938
3939                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3940                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3941         }
3942
3943         return res;
3944 }
3945
3946 static void
3947 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3948         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3949 {
3950         MonoClass *klass;
3951         guint32 idx, i;
3952
3953         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3954
3955         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3956
3957         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3958                                                                                                    parent_index, assembly);
3959
3960         /* 
3961          * Emit nested types
3962          * We need to do this ourselves since klass->nested_classes is not set up.
3963          */
3964         if (tb->subtypes) {
3965                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3966                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3967         }
3968 }
3969
3970 static void
3971 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3972         guint32 module_index, MonoDynamicImage *assembly)
3973 {
3974         MonoImage *image = module->image;
3975         MonoTableInfo  *t;
3976         guint32 i;
3977
3978         t = &image->tables [MONO_TABLE_TYPEDEF];
3979
3980         for (i = 0; i < t->rows; ++i) {
3981                 MonoError error;
3982                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3983                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3984
3985                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3986                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3987         }
3988 }
3989
3990 static void
3991 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3992 {
3993         MonoDynamicTable *table;
3994         guint32 *values;
3995         guint32 scope, scope_idx, impl, current_idx;
3996         gboolean forwarder = TRUE;
3997         gpointer iter = NULL;
3998         MonoClass *nested;
3999
4000         if (klass->nested_in) {
4001                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4002                 forwarder = FALSE;
4003         } else {
4004                 scope = resolution_scope_from_image (assembly, klass->image);
4005                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4006                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4007                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4008         }
4009
4010         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4011
4012         table->rows++;
4013         alloc_table (table, table->rows);
4014         current_idx = table->next_idx;
4015         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4016
4017         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4018         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4019         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4020         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4021         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4022
4023         table->next_idx++;
4024
4025         while ((nested = mono_class_get_nested_types (klass, &iter)))
4026                 add_exported_type (assemblyb, assembly, nested, current_idx);
4027 }
4028
4029 static void
4030 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4031 {
4032         MonoClass *klass;
4033         int i;
4034
4035         if (!assemblyb->type_forwarders)
4036                 return;
4037
4038         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4039                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4040                 MonoType *type;
4041                 if (!t)
4042                         continue;
4043
4044                 type = mono_reflection_type_get_handle (t);
4045                 g_assert (type);
4046
4047                 klass = mono_class_from_mono_type (type);
4048
4049                 add_exported_type (assemblyb, assembly, klass, 0);
4050         }
4051 }
4052
4053 #define align_pointer(base,p)\
4054         do {\
4055                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4056                 if (__diff & 3)\
4057                         (p) += 4 - (__diff & 3);\
4058         } while (0)
4059
4060 static int
4061 compare_constants (const void *a, const void *b)
4062 {
4063         const guint32 *a_values = a;
4064         const guint32 *b_values = b;
4065         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4066 }
4067
4068 static int
4069 compare_semantics (const void *a, const void *b)
4070 {
4071         const guint32 *a_values = a;
4072         const guint32 *b_values = b;
4073         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4074         if (assoc)
4075                 return assoc;
4076         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4077 }
4078
4079 static int
4080 compare_custom_attrs (const void *a, const void *b)
4081 {
4082         const guint32 *a_values = a;
4083         const guint32 *b_values = b;
4084
4085         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4086 }
4087
4088 static int
4089 compare_field_marshal (const void *a, const void *b)
4090 {
4091         const guint32 *a_values = a;
4092         const guint32 *b_values = b;
4093
4094         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4095 }
4096
4097 static int
4098 compare_nested (const void *a, const void *b)
4099 {
4100         const guint32 *a_values = a;
4101         const guint32 *b_values = b;
4102
4103         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4104 }
4105
4106 static int
4107 compare_genericparam (const void *a, const void *b)
4108 {
4109         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4110         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4111
4112         if ((*b_entry)->owner == (*a_entry)->owner)
4113                 return 
4114                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4115                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4116         else
4117                 return (*a_entry)->owner - (*b_entry)->owner;
4118 }
4119
4120 static int
4121 compare_declsecurity_attrs (const void *a, const void *b)
4122 {
4123         const guint32 *a_values = a;
4124         const guint32 *b_values = b;
4125
4126         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4127 }
4128
4129 static int
4130 compare_interface_impl (const void *a, const void *b)
4131 {
4132         const guint32 *a_values = a;
4133         const guint32 *b_values = b;
4134
4135         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4136         if (klass)
4137                 return klass;
4138
4139         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4140 }
4141
4142 static void
4143 pad_heap (MonoDynamicStream *sh)
4144 {
4145         if (sh->index & 3) {
4146                 int sz = 4 - (sh->index & 3);
4147                 memset (sh->data + sh->index, 0, sz);
4148                 sh->index += sz;
4149         }
4150 }
4151
4152 struct StreamDesc {
4153         const char *name;
4154         MonoDynamicStream *stream;
4155 };
4156
4157 /*
4158  * build_compressed_metadata() fills in the blob of data that represents the 
4159  * raw metadata as it will be saved in the PE file. The five streams are output 
4160  * and the metadata tables are comnpressed from the guint32 array representation, 
4161  * to the compressed on-disk format.
4162  */
4163 static void
4164 build_compressed_metadata (MonoDynamicImage *assembly)
4165 {
4166         MonoDynamicTable *table;
4167         int i;
4168         guint64 valid_mask = 0;
4169         guint64 sorted_mask;
4170         guint32 heapt_size = 0;
4171         guint32 meta_size = 256; /* allow for header and other stuff */
4172         guint32 table_offset;
4173         guint32 ntables = 0;
4174         guint64 *int64val;
4175         guint32 *int32val;
4176         guint16 *int16val;
4177         MonoImage *meta;
4178         unsigned char *p;
4179         struct StreamDesc stream_desc [5];
4180
4181         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4182         for (i = 0; i < assembly->gen_params->len; i++){
4183                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4184                 write_generic_param_entry (assembly, entry);
4185         }
4186
4187         stream_desc [0].name  = "#~";
4188         stream_desc [0].stream = &assembly->tstream;
4189         stream_desc [1].name  = "#Strings";
4190         stream_desc [1].stream = &assembly->sheap;
4191         stream_desc [2].name  = "#US";
4192         stream_desc [2].stream = &assembly->us;
4193         stream_desc [3].name  = "#Blob";
4194         stream_desc [3].stream = &assembly->blob;
4195         stream_desc [4].name  = "#GUID";
4196         stream_desc [4].stream = &assembly->guid;
4197         
4198         /* tables that are sorted */
4199         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4200                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4201                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4202                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4203                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4204                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4205                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4206         
4207         /* Compute table sizes */
4208         /* the MonoImage has already been created in mono_image_basic_init() */
4209         meta = &assembly->image;
4210
4211         /* sizes should be multiple of 4 */
4212         pad_heap (&assembly->blob);
4213         pad_heap (&assembly->guid);
4214         pad_heap (&assembly->sheap);
4215         pad_heap (&assembly->us);
4216
4217         /* Setup the info used by compute_sizes () */
4218         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4219         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4220         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4221
4222         meta_size += assembly->blob.index;
4223         meta_size += assembly->guid.index;
4224         meta_size += assembly->sheap.index;
4225         meta_size += assembly->us.index;
4226
4227         for (i=0; i < MONO_TABLE_NUM; ++i)
4228                 meta->tables [i].rows = assembly->tables [i].rows;
4229         
4230         for (i = 0; i < MONO_TABLE_NUM; i++){
4231                 if (meta->tables [i].rows == 0)
4232                         continue;
4233                 valid_mask |= (guint64)1 << i;
4234                 ntables ++;
4235                 meta->tables [i].row_size = mono_metadata_compute_size (
4236                         meta, i, &meta->tables [i].size_bitfield);
4237                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4238         }
4239         heapt_size += 24; /* #~ header size */
4240         heapt_size += ntables * 4;
4241         /* make multiple of 4 */
4242         heapt_size += 3;
4243         heapt_size &= ~3;
4244         meta_size += heapt_size;
4245         meta->raw_metadata = g_malloc0 (meta_size);
4246         p = (unsigned char*)meta->raw_metadata;
4247         /* the metadata signature */
4248         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4249         /* version numbers and 4 bytes reserved */
4250         int16val = (guint16*)p;
4251         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4252         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4253         p += 8;
4254         /* version string */
4255         int32val = (guint32*)p;
4256         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4257         p += 4;
4258         memcpy (p, meta->version, strlen (meta->version));
4259         p += GUINT32_FROM_LE (*int32val);
4260         align_pointer (meta->raw_metadata, p);
4261         int16val = (guint16*)p;
4262         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4263         *int16val = GUINT16_TO_LE (5); /* number of streams */
4264         p += 4;
4265
4266         /*
4267          * write the stream info.
4268          */
4269         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4270         table_offset += 3; table_offset &= ~3;
4271
4272         assembly->tstream.index = heapt_size;
4273         for (i = 0; i < 5; ++i) {
4274                 int32val = (guint32*)p;
4275                 stream_desc [i].stream->offset = table_offset;
4276                 *int32val++ = GUINT32_TO_LE (table_offset);
4277                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4278                 table_offset += GUINT32_FROM_LE (*int32val);
4279                 table_offset += 3; table_offset &= ~3;
4280                 p += 8;
4281                 strcpy ((char*)p, stream_desc [i].name);
4282                 p += strlen (stream_desc [i].name) + 1;
4283                 align_pointer (meta->raw_metadata, p);
4284         }
4285         /* 
4286          * now copy the data, the table stream header and contents goes first.
4287          */
4288         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4289         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4290         int32val = (guint32*)p;
4291         *int32val = GUINT32_TO_LE (0); /* reserved */
4292         p += 4;
4293
4294         *p++ = 2; /* version */
4295         *p++ = 0;
4296
4297         if (meta->idx_string_wide)
4298                 *p |= 0x01;
4299         if (meta->idx_guid_wide)
4300                 *p |= 0x02;
4301         if (meta->idx_blob_wide)
4302                 *p |= 0x04;
4303         ++p;
4304         *p++ = 1; /* reserved */
4305         int64val = (guint64*)p;
4306         *int64val++ = GUINT64_TO_LE (valid_mask);
4307         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4308         p += 16;
4309         int32val = (guint32*)p;
4310         for (i = 0; i < MONO_TABLE_NUM; i++){
4311                 if (meta->tables [i].rows == 0)
4312                         continue;
4313                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4314         }
4315         p = (unsigned char*)int32val;
4316
4317         /* sort the tables that still need sorting */
4318         table = &assembly->tables [MONO_TABLE_CONSTANT];
4319         if (table->rows)
4320                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4321         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4322         if (table->rows)
4323                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4324         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4325         if (table->rows)
4326                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4327         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4328         if (table->rows)
4329                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4330         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4331         if (table->rows)
4332                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4333         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4334         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4335         if (table->rows)
4336                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4337         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4338         if (table->rows)
4339                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4340
4341         /* compress the tables */
4342         for (i = 0; i < MONO_TABLE_NUM; i++){
4343                 int row, col;
4344                 guint32 *values;
4345                 guint32 bitfield = meta->tables [i].size_bitfield;
4346                 if (!meta->tables [i].rows)
4347                         continue;
4348                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4349                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4350                 meta->tables [i].base = (char*)p;
4351                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4352                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4353                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4354                                 switch (mono_metadata_table_size (bitfield, col)) {
4355                                 case 1:
4356                                         *p++ = values [col];
4357                                         break;
4358                                 case 2:
4359                                         *p++ = values [col] & 0xff;
4360                                         *p++ = (values [col] >> 8) & 0xff;
4361                                         break;
4362                                 case 4:
4363                                         *p++ = values [col] & 0xff;
4364                                         *p++ = (values [col] >> 8) & 0xff;
4365                                         *p++ = (values [col] >> 16) & 0xff;
4366                                         *p++ = (values [col] >> 24) & 0xff;
4367                                         break;
4368                                 default:
4369                                         g_assert_not_reached ();
4370                                 }
4371                         }
4372                 }
4373                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4374         }
4375         
4376         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4377         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4378         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4379         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4380         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4381
4382         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4383 }
4384
4385 /*
4386  * Some tables in metadata need to be sorted according to some criteria, but
4387  * when methods and fields are first created with reflection, they may be assigned a token
4388  * that doesn't correspond to the final token they will get assigned after the sorting.
4389  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4390  * with the reflection objects that represent them. Once all the tables are set up, the 
4391  * reflection objects will contains the correct table index. fixup_method() will fixup the
4392  * tokens for the method with ILGenerator @ilgen.
4393  */
4394 static void
4395 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4396 {
4397         guint32 code_idx = GPOINTER_TO_UINT (value);
4398         MonoReflectionILTokenInfo *iltoken;
4399         MonoReflectionFieldBuilder *field;
4400         MonoReflectionCtorBuilder *ctor;
4401         MonoReflectionMethodBuilder *method;
4402         MonoReflectionTypeBuilder *tb;
4403         MonoReflectionArrayMethod *am;
4404         guint32 i, idx = 0;
4405         unsigned char *target;
4406
4407         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4408                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4409                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4410                 switch (target [3]) {
4411                 case MONO_TABLE_FIELD:
4412                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4413                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4414                                 idx = field->table_idx;
4415                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4416                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4417                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4418                         } else {
4419                                 g_assert_not_reached ();
4420                         }
4421                         break;
4422                 case MONO_TABLE_METHOD:
4423                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4424                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4425                                 idx = method->table_idx;
4426                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4427                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4428                                 idx = ctor->table_idx;
4429                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4430                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4431                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4432                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4433                         } else {
4434                                 g_assert_not_reached ();
4435                         }
4436                         break;
4437                 case MONO_TABLE_TYPEDEF:
4438                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4439                                 g_assert_not_reached ();
4440                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4441                         idx = tb->table_idx;
4442                         break;
4443                 case MONO_TABLE_MEMBERREF:
4444                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4445                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4446                                 idx = am->table_idx;
4447                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4448                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4449                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4450                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4451                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4452                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4453                                 continue;
4454                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4455                                 continue;
4456                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4457                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4458                                 g_assert (is_field_on_inst (f));
4459                                 continue;
4460                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4461                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4462                                 continue;
4463                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4464                                 continue;
4465                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4466                                 continue;
4467                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4468                                 continue;
4469                         } else {
4470                                 g_assert_not_reached ();
4471                         }
4472                         break;
4473                 case MONO_TABLE_METHODSPEC:
4474                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4475                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4476                                 g_assert (mono_method_signature (m)->generic_param_count);
4477                                 continue;
4478                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4479                                 continue;
4480                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4481                                 continue;
4482                         } else {
4483                                 g_assert_not_reached ();
4484                         }
4485                         break;
4486                 default:
4487                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4488                 }
4489                 target [0] = idx & 0xff;
4490                 target [1] = (idx >> 8) & 0xff;
4491                 target [2] = (idx >> 16) & 0xff;
4492         }
4493 }
4494
4495 /*
4496  * fixup_cattrs:
4497  *
4498  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4499  * value is not known when the table is emitted.
4500  */
4501 static void
4502 fixup_cattrs (MonoDynamicImage *assembly)
4503 {
4504         MonoDynamicTable *table;
4505         guint32 *values;
4506         guint32 type, i, idx, token;
4507         MonoObject *ctor;
4508
4509         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4510
4511         for (i = 0; i < table->rows; ++i) {
4512                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4513
4514                 type = values [MONO_CUSTOM_ATTR_TYPE];
4515                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4516                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4517                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4518                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4519                         g_assert (ctor);
4520
4521                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4522                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4523                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4524                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4525                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4526                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4527                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4528                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4529                         }
4530                 }
4531         }
4532 }
4533
4534 static void
4535 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4536 {
4537         MonoDynamicTable *table;
4538         guint32 *values;
4539
4540         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4541         table->rows++;
4542         alloc_table (table, table->rows);
4543         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4544         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4545         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4546         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4547         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4548         table->next_idx++;
4549 }
4550
4551 static void
4552 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4553 {
4554         MonoDynamicTable *table;
4555         guint32 *values;
4556         char blob_size [6];
4557         guchar hash [20];
4558         char *b = blob_size;
4559         char *name, *sname;
4560         guint32 idx, offset;
4561
4562         if (rsrc->filename) {
4563                 name = mono_string_to_utf8 (rsrc->filename);
4564                 sname = g_path_get_basename (name);
4565         
4566                 table = &assembly->tables [MONO_TABLE_FILE];
4567                 table->rows++;
4568                 alloc_table (table, table->rows);
4569                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4570                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4571                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4572                 g_free (sname);
4573
4574                 mono_sha1_get_digest_from_file (name, hash);
4575                 mono_metadata_encode_value (20, b, &b);
4576                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4577                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4578                 g_free (name);
4579                 idx = table->next_idx++;
4580                 rsrc->offset = 0;
4581                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4582         } else {
4583                 char sizebuf [4];
4584                 char *data;
4585                 guint len;
4586                 if (rsrc->data) {
4587                         data = mono_array_addr (rsrc->data, char, 0);
4588                         len = mono_array_length (rsrc->data);
4589                 } else {
4590                         data = NULL;
4591                         len = 0;
4592                 }
4593                 offset = len;
4594                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4595                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4596                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4597                 mono_image_add_stream_data (&assembly->resources, data, len);
4598
4599                 if (!mb->is_main)
4600                         /* 
4601                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4602                          * the main module, but that needs to reference the FILE table
4603                          * which isn't emitted yet.
4604                          */
4605                         return;
4606                 else
4607                         idx = 0;
4608         }
4609
4610         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4611 }
4612
4613 static void
4614 set_version_from_string (MonoString *version, guint32 *values)
4615 {
4616         gchar *ver, *p, *str;
4617         guint32 i;
4618         
4619         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4620         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4621         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4622         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4623         if (!version)
4624                 return;
4625         ver = str = mono_string_to_utf8 (version);
4626         for (i = 0; i < 4; ++i) {
4627                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4628                 switch (*p) {
4629                 case '.':
4630                         p++;
4631                         break;
4632                 case '*':
4633                         /* handle Revision and Build */
4634                         p++;
4635                         break;
4636                 }
4637                 ver = p;
4638         }
4639         g_free (str);
4640 }
4641
4642 static guint32
4643 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4644         gsize len;
4645         guint32 token = 0;
4646         char blob_size [6];
4647         char *b = blob_size;
4648
4649         if (!pkey)
4650                 return token;
4651
4652         len = mono_array_length (pkey);
4653         mono_metadata_encode_value (len, b, &b);
4654         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4655         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4656
4657         assembly->public_key = g_malloc (len);
4658         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4659         assembly->public_key_len = len;
4660
4661         /* Special case: check for ECMA key (16 bytes) */
4662         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4663                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4664                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4665         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4666                 /* minimum key size (in 2.0) is 384 bits */
4667                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4668         } else {
4669                 /* FIXME - verifier */
4670                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4671                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4672         }
4673         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4674
4675         return token;
4676 }
4677
4678 static void
4679 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4680 {
4681         MonoDynamicTable *table;
4682         MonoDynamicImage *assembly;
4683         MonoReflectionAssemblyBuilder *assemblyb;
4684         MonoDomain *domain;
4685         guint32 *values;
4686         int i;
4687         guint32 module_index;
4688
4689         assemblyb = moduleb->assemblyb;
4690         assembly = moduleb->dynamic_image;
4691         domain = mono_object_domain (assemblyb);
4692
4693         /* Emit ASSEMBLY table */
4694         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4695         alloc_table (table, 1);
4696         values = table->values + MONO_ASSEMBLY_SIZE;
4697         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4698         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4699         if (assemblyb->culture) {
4700                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4701         } else {
4702                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4703         }
4704         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4705         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4706         set_version_from_string (assemblyb->version, values);
4707
4708         /* Emit FILE + EXPORTED_TYPE table */
4709         module_index = 0;
4710         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4711                 int j;
4712                 MonoReflectionModuleBuilder *file_module = 
4713                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4714                 if (file_module != moduleb) {
4715                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4716                         module_index ++;
4717                         if (file_module->types) {
4718                                 for (j = 0; j < file_module->num_types; ++j) {
4719                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4720                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4721                                 }
4722                         }
4723                 }
4724         }
4725         if (assemblyb->loaded_modules) {
4726                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4727                         MonoReflectionModule *file_module = 
4728                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4729                         mono_image_fill_file_table (domain, file_module, assembly);
4730                         module_index ++;
4731                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4732                 }
4733         }
4734         if (assemblyb->type_forwarders)
4735                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4736
4737         /* Emit MANIFESTRESOURCE table */
4738         module_index = 0;
4739         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4740                 int j;
4741                 MonoReflectionModuleBuilder *file_module = 
4742                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4743                 /* The table for the main module is emitted later */
4744                 if (file_module != moduleb) {
4745                         module_index ++;
4746                         if (file_module->resources) {
4747                                 int len = mono_array_length (file_module->resources);
4748                                 for (j = 0; j < len; ++j) {
4749                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4750                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4751                                 }
4752                         }
4753                 }
4754         }               
4755 }
4756
4757 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4758
4759 /*
4760  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4761  * for the modulebuilder @moduleb.
4762  * At the end of the process, method and field tokens are fixed up and the 
4763  * on-disk compressed metadata representation is created.
4764  */
4765 void
4766 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4767 {
4768         MonoDynamicTable *table;
4769         MonoDynamicImage *assembly;
4770         MonoReflectionAssemblyBuilder *assemblyb;
4771         MonoDomain *domain;
4772         MonoPtrArray types;
4773         guint32 *values;
4774         int i, j;
4775
4776         assemblyb = moduleb->assemblyb;
4777         assembly = moduleb->dynamic_image;
4778         domain = mono_object_domain (assemblyb);
4779
4780         if (assembly->text_rva)
4781                 return;
4782
4783         assembly->text_rva = START_TEXT_RVA;
4784
4785         if (moduleb->is_main) {
4786                 mono_image_emit_manifest (moduleb);
4787         }
4788
4789         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4790         table->rows = 1; /* .<Module> */
4791         table->next_idx++;
4792         alloc_table (table, table->rows);
4793         /*
4794          * Set the first entry.
4795          */
4796         values = table->values + table->columns;
4797         values [MONO_TYPEDEF_FLAGS] = 0;
4798         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4799         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4800         values [MONO_TYPEDEF_EXTENDS] = 0;
4801         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4802         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4803
4804         /* 
4805          * handle global methods 
4806          * FIXME: test what to do when global methods are defined in multiple modules.
4807          */
4808         if (moduleb->global_methods) {
4809                 table = &assembly->tables [MONO_TABLE_METHOD];
4810                 table->rows += mono_array_length (moduleb->global_methods);
4811                 alloc_table (table, table->rows);
4812                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4813                         mono_image_get_method_info (
4814                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4815         }
4816         if (moduleb->global_fields) {
4817                 table = &assembly->tables [MONO_TABLE_FIELD];
4818                 table->rows += mono_array_length (moduleb->global_fields);
4819                 alloc_table (table, table->rows);
4820                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4821                         mono_image_get_field_info (
4822                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4823         }
4824
4825         table = &assembly->tables [MONO_TABLE_MODULE];
4826         alloc_table (table, 1);
4827         mono_image_fill_module_table (domain, moduleb, assembly);
4828
4829         /* Collect all types into a list sorted by their table_idx */
4830         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4831
4832         if (moduleb->types)
4833                 for (i = 0; i < moduleb->num_types; ++i) {
4834                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4835                         collect_types (&types, type);
4836                 }
4837
4838         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4839         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840         table->rows += mono_ptr_array_size (types);
4841         alloc_table (table, table->rows);
4842
4843         /*
4844          * Emit type names + namespaces at one place inside the string heap,
4845          * so load_class_names () needs to touch fewer pages.
4846          */
4847         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4848                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4849                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4850         }
4851         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4852                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4853                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4854         }
4855
4856         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4857                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4858                 mono_image_get_type_info (domain, type, assembly);
4859         }
4860
4861         /* 
4862          * table->rows is already set above and in mono_image_fill_module_table.
4863          */
4864         /* add all the custom attributes at the end, once all the indexes are stable */
4865         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4866
4867         /* CAS assembly permissions */
4868         if (assemblyb->permissions_minimum)
4869                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4870         if (assemblyb->permissions_optional)
4871                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4872         if (assemblyb->permissions_refused)
4873                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4874
4875         module_add_cattrs (assembly, moduleb);
4876
4877         /* fixup tokens */
4878         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4879
4880         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4881          * the final tokens and don't need another fixup pass. */
4882
4883         if (moduleb->global_methods) {
4884                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4885                         MonoReflectionMethodBuilder *mb = mono_array_get (
4886                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4887                         mono_image_add_methodimpl (assembly, mb);
4888                 }
4889         }
4890
4891         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4892                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4893                 if (type->methods) {
4894                         for (j = 0; j < type->num_methods; ++j) {
4895                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4896                                         type->methods, MonoReflectionMethodBuilder*, j);
4897
4898                                 mono_image_add_methodimpl (assembly, mb);
4899                         }
4900                 }
4901         }
4902
4903         mono_ptr_array_destroy (types);
4904
4905         fixup_cattrs (assembly);
4906 }
4907
4908 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4909
4910 void
4911 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4912 {
4913         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4914 }
4915
4916 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4917
4918
4919 typedef struct {
4920         guint32 import_lookup_table;
4921         guint32 timestamp;
4922         guint32 forwarder;
4923         guint32 name_rva;
4924         guint32 import_address_table_rva;
4925 } MonoIDT;
4926
4927 typedef struct {
4928         guint32 name_rva;
4929         guint32 flags;
4930 } MonoILT;
4931
4932 #ifndef DISABLE_REFLECTION_EMIT
4933
4934 /*
4935  * mono_image_insert_string:
4936  * @module: module builder object
4937  * @str: a string
4938  *
4939  * Insert @str into the user string stream of @module.
4940  */
4941 guint32
4942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4943 {
4944         MonoDynamicImage *assembly;
4945         guint32 idx;
4946         char buf [16];
4947         char *b = buf;
4948         
4949         if (!module->dynamic_image)
4950                 mono_image_module_basic_init (module);
4951
4952         assembly = module->dynamic_image;
4953         
4954         if (assembly->save) {
4955                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4956                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4957 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4958         {
4959                 char *swapped = g_malloc (2 * mono_string_length (str));
4960                 const char *p = (const char*)mono_string_chars (str);
4961
4962                 swap_with_size (swapped, p, 2, mono_string_length (str));
4963                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4964                 g_free (swapped);
4965         }
4966 #else
4967                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4968 #endif
4969                 mono_image_add_stream_data (&assembly->us, "", 1);
4970         } else {
4971                 idx = assembly->us.index ++;
4972         }
4973
4974         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
4975
4976         return MONO_TOKEN_STRING | idx;
4977 }
4978
4979 guint32
4980 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4981 {
4982         MonoClass *klass;
4983         guint32 token = 0;
4984         MonoMethodSignature *sig;
4985
4986         klass = obj->vtable->klass;
4987         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4988                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4989                 MonoMethodSignature *old;
4990                 guint32 sig_token, parent;
4991                 int nargs, i;
4992
4993                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4994
4995                 nargs = mono_array_length (opt_param_types);
4996                 old = mono_method_signature (method);
4997                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4998
4999                 sig->hasthis = old->hasthis;
5000                 sig->explicit_this = old->explicit_this;
5001                 sig->call_convention = old->call_convention;
5002                 sig->generic_param_count = old->generic_param_count;
5003                 sig->param_count = old->param_count + nargs;
5004                 sig->sentinelpos = old->param_count;
5005                 sig->ret = old->ret;
5006
5007                 for (i = 0; i < old->param_count; i++)
5008                         sig->params [i] = old->params [i];
5009
5010                 for (i = 0; i < nargs; i++) {
5011                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5012                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5013                 }
5014
5015                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5016                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5017                 parent >>= MONO_TYPEDEFORREF_BITS;
5018
5019                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5020                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5021
5022                 sig_token = method_encode_signature (assembly, sig);
5023                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5024         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5025                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5026                 ReflectionMethodBuilder rmb;
5027                 guint32 parent, sig_token;
5028                 int nopt_args, nparams, ngparams, i;
5029                 char *name;
5030
5031                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5032                 rmb.opt_types = opt_param_types;
5033                 nopt_args = mono_array_length (opt_param_types);
5034
5035                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5036                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5037                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5038
5039                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5040                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5041                 sig->call_convention = rmb.call_conv;
5042                 sig->generic_param_count = ngparams;
5043                 sig->param_count = nparams + nopt_args;
5044                 sig->sentinelpos = nparams;
5045                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5046
5047                 for (i = 0; i < nparams; i++) {
5048                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5049                         sig->params [i] = mono_reflection_type_get_handle (rt);
5050                 }
5051
5052                 for (i = 0; i < nopt_args; i++) {
5053                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5054                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5055                 }
5056
5057                 sig_token = method_builder_encode_signature (assembly, &rmb);
5058
5059                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5060                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5061
5062                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5063                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5064
5065                 name = mono_string_to_utf8 (rmb.name);
5066                 token = mono_image_get_varargs_method_token (
5067                         assembly, parent, name, sig_token);
5068                 g_free (name);
5069         } else {
5070                 g_error ("requested method token for %s\n", klass->name);
5071         }
5072
5073         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5074         register_dyn_token (assembly, token, obj);
5075         return token;
5076 }
5077
5078 /*
5079  * mono_image_create_token:
5080  * @assembly: a dynamic assembly
5081  * @obj:
5082  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5083  *
5084  * Get a token to insert in the IL code stream for the given MemberInfo.
5085  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5086  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5087  * entry.
5088  */
5089 guint32
5090 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5091                                                  gboolean create_open_instance, gboolean register_token)
5092 {
5093         MonoClass *klass;
5094         guint32 token = 0;
5095
5096         klass = obj->vtable->klass;
5097
5098         /* Check for user defined reflection objects */
5099         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5100         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5101                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5102
5103         if (strcmp (klass->name, "MethodBuilder") == 0) {
5104                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5105                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5106
5107                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5108                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5109                 else
5110                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5111                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5112         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5113                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5114                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5115
5116                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5117                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5118                 else
5119                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5120                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5121         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5122                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5123                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5124                 if (tb->generic_params) {
5125                         token = mono_image_get_generic_field_token (assembly, fb);
5126                 } else {
5127                         if (tb->module->dynamic_image == assembly) {
5128                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5129                         } else {
5130                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5131                         }
5132                 }
5133         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5134                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5135                 if (create_open_instance && tb->generic_params) {
5136                         MonoType *type;
5137                         init_type_builder_generics (obj);
5138                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5139                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5140                         token = mono_metadata_token_from_dor (token);
5141                 } else if (tb->module->dynamic_image == assembly) {
5142                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5143                 } else {
5144                         MonoType *type;
5145                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5146                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5147                 }
5148         } else if (strcmp (klass->name, "MonoType") == 0) {
5149                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5150                 MonoClass *mc = mono_class_from_mono_type (type);
5151                 token = mono_metadata_token_from_dor (
5152                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5153         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5154                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5155                 token = mono_metadata_token_from_dor (
5156                         mono_image_typedef_or_ref (assembly, type));
5157         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5158                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5159                 token = mono_metadata_token_from_dor (
5160                         mono_image_typedef_or_ref (assembly, type));
5161         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5162                    strcmp (klass->name, "MonoMethod") == 0 ||
5163                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5164                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5165                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5166                 if (m->method->is_inflated) {
5167                         if (create_open_instance)
5168                                 token = mono_image_get_methodspec_token (assembly, m->method);
5169                         else
5170                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5171                 } else if ((m->method->klass->image == &assembly->image) &&
5172                          !m->method->klass->generic_class) {
5173                         static guint32 method_table_idx = 0xffffff;
5174                         if (m->method->klass->wastypebuilder) {
5175                                 /* we use the same token as the one that was assigned
5176                                  * to the Methodbuilder.
5177                                  * FIXME: do the equivalent for Fields.
5178                                  */
5179                                 token = m->method->token;
5180                         } else {
5181                                 /*
5182                                  * Each token should have a unique index, but the indexes are
5183                                  * assigned by managed code, so we don't know about them. An
5184                                  * easy solution is to count backwards...
5185                                  */
5186                                 method_table_idx --;
5187                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5188                         }
5189                 } else {
5190                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5191                 }
5192                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5193         } else if (strcmp (klass->name, "MonoField") == 0) {
5194                 MonoReflectionField *f = (MonoReflectionField *)obj;
5195                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5196                         static guint32 field_table_idx = 0xffffff;
5197                         field_table_idx --;
5198                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5199                 } else {
5200                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5201                 }
5202                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5203         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5204                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5205                 token = mono_image_get_array_token (assembly, m);
5206         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5207                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5208                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5209         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5210                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5211                 token = mono_metadata_token_from_dor (
5212                         mono_image_typedef_or_ref (assembly, type));
5213         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5214                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5215                 token = mono_image_get_field_on_inst_token (assembly, f);
5216         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5217                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5218                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5219         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5220                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5221                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5222         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5223                 MonoReflectionType *type = (MonoReflectionType *)obj;
5224                 token = mono_metadata_token_from_dor (
5225                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5226         } else {
5227                 g_error ("requested token for %s\n", klass->name);
5228         }
5229
5230         if (register_token)
5231                 mono_image_register_token (assembly, token, obj);
5232
5233         return token;
5234 }
5235
5236 /*
5237  * mono_image_register_token:
5238  *
5239  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5240  * the Module.ResolveXXXToken () methods to work.
5241  */
5242 void
5243 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5244 {
5245         MonoObject *prev;
5246
5247         dynamic_image_lock (assembly);
5248         prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5249         if (prev) {
5250                 /* There could be multiple MethodInfo objects with the same token */
5251                 //g_assert (prev == obj);
5252         } else {
5253                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5254         }
5255         dynamic_image_unlock (assembly);
5256 }
5257
5258 static MonoDynamicImage*
5259 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5260 {
5261         static const guchar entrycode [16] = {0xff, 0x25, 0};
5262         MonoDynamicImage *image;
5263         int i;
5264
5265         const char *version;
5266
5267         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5268                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5269         else
5270                 version = mono_get_runtime_info ()->runtime_version;
5271
5272 #if HAVE_BOEHM_GC
5273         /* The MonoGHashTable's need GC tracking */
5274         image = GC_MALLOC (sizeof (MonoDynamicImage));
5275 #else
5276         image = g_new0 (MonoDynamicImage, 1);
5277 #endif
5278
5279         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5280         
5281         /*g_print ("created image %p\n", image);*/
5282         /* keep in sync with image.c */
5283         image->image.name = assembly_name;
5284         image->image.assembly_name = image->image.name; /* they may be different */
5285         image->image.module_name = module_name;
5286         image->image.version = g_strdup (version);
5287         image->image.md_version_major = 1;
5288         image->image.md_version_minor = 1;
5289         image->image.dynamic = TRUE;
5290
5291         image->image.references = g_new0 (MonoAssembly*, 1);
5292         image->image.references [0] = NULL;
5293
5294         mono_image_init (&image->image);
5295
5296         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");
5297         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5298         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5299         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5300         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5301         image->handleref = g_hash_table_new (NULL, NULL);
5302         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");
5303         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5304         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");
5305         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");
5306         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5307         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5308         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5309         image->gen_params = g_ptr_array_new ();
5310         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5311
5312         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5313         string_heap_init (&image->sheap);
5314         mono_image_add_stream_data (&image->us, "", 1);
5315         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5316         /* import tables... */
5317         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5318         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5319         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5320         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5321         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5322         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5323         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5324         stream_data_align (&image->code);
5325
5326         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5327
5328         for (i=0; i < MONO_TABLE_NUM; ++i) {
5329                 image->tables [i].next_idx = 1;
5330                 image->tables [i].columns = table_sizes [i];
5331         }
5332
5333         image->image.assembly = (MonoAssembly*)assembly;
5334         image->run = assembly->run;
5335         image->save = assembly->save;
5336         image->pe_kind = 0x1; /* ILOnly */
5337         image->machine = 0x14c; /* I386 */
5338         
5339         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5340
5341         return image;
5342 }
5343 #endif
5344
5345 static void
5346 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5347 {
5348         g_free (key);
5349 }
5350
5351 static void
5352 release_hashtable (MonoGHashTable **hash)
5353 {
5354         if (*hash) {
5355                 mono_g_hash_table_destroy (*hash);
5356                 *hash = NULL;
5357         }
5358 }
5359
5360 void
5361 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5362 {
5363         release_hashtable (&image->token_fixups);
5364         release_hashtable (&image->handleref_managed);
5365         release_hashtable (&image->tokens);
5366         release_hashtable (&image->remapped_tokens);
5367         release_hashtable (&image->generic_def_objects);
5368         release_hashtable (&image->methodspec);
5369 }
5370
5371 void
5372 mono_dynamic_image_free (MonoDynamicImage *image)
5373 {
5374         MonoDynamicImage *di = image;
5375         GList *list;
5376         int i;
5377
5378         if (di->methodspec)
5379                 mono_g_hash_table_destroy (di->methodspec);
5380         if (di->typespec)
5381                 g_hash_table_destroy (di->typespec);
5382         if (di->typeref)
5383                 g_hash_table_destroy (di->typeref);
5384         if (di->handleref)
5385                 g_hash_table_destroy (di->handleref);
5386         if (di->handleref_managed)
5387                 mono_g_hash_table_destroy (di->handleref_managed);
5388         if (di->tokens)
5389                 mono_g_hash_table_destroy (di->tokens);
5390         if (di->remapped_tokens)
5391                 mono_g_hash_table_destroy (di->remapped_tokens);
5392         if (di->generic_def_objects)
5393                 mono_g_hash_table_destroy (di->generic_def_objects);
5394         if (di->blob_cache) {
5395                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5396                 g_hash_table_destroy (di->blob_cache);
5397         }
5398         if (di->standalonesig_cache)
5399                 g_hash_table_destroy (di->standalonesig_cache);
5400         for (list = di->array_methods; list; list = list->next) {
5401                 ArrayMethod *am = (ArrayMethod *)list->data;
5402                 g_free (am->sig);
5403                 g_free (am->name);
5404                 g_free (am);
5405         }
5406         g_list_free (di->array_methods);
5407         if (di->gen_params) {
5408                 for (i = 0; i < di->gen_params->len; i++) {
5409                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5410                         mono_gc_deregister_root ((char*) &entry->gparam);
5411                         g_free (entry);
5412                 }
5413                 g_ptr_array_free (di->gen_params, TRUE);
5414         }
5415         if (di->token_fixups)
5416                 mono_g_hash_table_destroy (di->token_fixups);
5417         if (di->method_to_table_idx)
5418                 g_hash_table_destroy (di->method_to_table_idx);
5419         if (di->field_to_table_idx)
5420                 g_hash_table_destroy (di->field_to_table_idx);
5421         if (di->method_aux_hash)
5422                 g_hash_table_destroy (di->method_aux_hash);
5423         if (di->vararg_aux_hash)
5424                 g_hash_table_destroy (di->vararg_aux_hash);
5425         g_free (di->strong_name);
5426         g_free (di->win32_res);
5427         if (di->public_key)
5428                 g_free (di->public_key);
5429
5430         /*g_print ("string heap destroy for image %p\n", di);*/
5431         mono_dynamic_stream_reset (&di->sheap);
5432         mono_dynamic_stream_reset (&di->code);
5433         mono_dynamic_stream_reset (&di->resources);
5434         mono_dynamic_stream_reset (&di->us);
5435         mono_dynamic_stream_reset (&di->blob);
5436         mono_dynamic_stream_reset (&di->tstream);
5437         mono_dynamic_stream_reset (&di->guid);
5438         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5439                 g_free (di->tables [i].values);
5440         }
5441 }       
5442
5443 void
5444 mono_dynamic_image_free_image (MonoDynamicImage *image)
5445 {
5446         /* See create_dynamic_mono_image () */
5447 #if HAVE_BOEHM_GC
5448         /* Allocated using GC_MALLOC */
5449 #else
5450         g_free (image);
5451 #endif
5452 }
5453
5454 #ifndef DISABLE_REFLECTION_EMIT
5455
5456 /*
5457  * mono_image_basic_init:
5458  * @assembly: an assembly builder object
5459  *
5460  * Create the MonoImage that represents the assembly builder and setup some
5461  * of the helper hash table and the basic metadata streams.
5462  */
5463 void
5464 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5465 {
5466         MonoDynamicAssembly *assembly;
5467         MonoDynamicImage *image;
5468         MonoDomain *domain = mono_object_domain (assemblyb);
5469         
5470         if (assemblyb->dynamic_assembly)
5471                 return;
5472
5473 #if HAVE_BOEHM_GC
5474         /* assembly->assembly.image might be GC allocated */
5475         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5476 #else
5477         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5478 #endif
5479
5480         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5481         
5482         assembly->assembly.ref_count = 1;
5483         assembly->assembly.dynamic = TRUE;
5484         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5485         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5486         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5487         if (assemblyb->culture)
5488                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5489         else
5490                 assembly->assembly.aname.culture = g_strdup ("");
5491
5492         if (assemblyb->version) {
5493                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5494                         char **version = g_strsplit (vstr, ".", 4);
5495                         char **parts = version;
5496                         assembly->assembly.aname.major = atoi (*parts++);
5497                         assembly->assembly.aname.minor = atoi (*parts++);
5498                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5499                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5500
5501                         g_strfreev (version);
5502                         g_free (vstr);
5503         } else {
5504                         assembly->assembly.aname.major = 0;
5505                         assembly->assembly.aname.minor = 0;
5506                         assembly->assembly.aname.build = 0;
5507                         assembly->assembly.aname.revision = 0;
5508         }
5509
5510         assembly->run = assemblyb->access != 2;
5511         assembly->save = assemblyb->access != 1;
5512         assembly->domain = domain;
5513
5514         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5515         image->initial_image = TRUE;
5516         assembly->assembly.aname.name = image->image.name;
5517         assembly->assembly.image = &image->image;
5518         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5519                 /* -1 to correct for the trailing NULL byte */
5520                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5521                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5522                 }
5523                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5524         }
5525
5526         mono_domain_assemblies_lock (domain);
5527         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5528         mono_domain_assemblies_unlock (domain);
5529
5530         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5531         
5532         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5533         
5534         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5535 }
5536
5537 #endif /* !DISABLE_REFLECTION_EMIT */
5538
5539 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5540
5541 static int
5542 calc_section_size (MonoDynamicImage *assembly)
5543 {
5544         int nsections = 0;
5545
5546         /* alignment constraints */
5547         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5548         g_assert ((assembly->code.index % 4) == 0);
5549         assembly->meta_size += 3;
5550         assembly->meta_size &= ~3;
5551         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5552         g_assert ((assembly->resources.index % 4) == 0);
5553
5554         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5555         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5556         nsections++;
5557
5558         if (assembly->win32_res) {
5559                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5560
5561                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5562                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5563                 nsections++;
5564         }
5565
5566         assembly->sections [MONO_SECTION_RELOC].size = 12;
5567         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5568         nsections++;
5569
5570         return nsections;
5571 }
5572
5573 typedef struct {
5574         guint32 id;
5575         guint32 offset;
5576         GSList *children;
5577         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5578 } ResTreeNode;
5579
5580 static int
5581 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5582 {
5583         ResTreeNode *t1 = (ResTreeNode*)a;
5584         ResTreeNode *t2 = (ResTreeNode*)b;
5585
5586         return t1->id - t2->id;
5587 }
5588
5589 /*
5590  * resource_tree_create:
5591  *
5592  *  Organize the resources into a resource tree.
5593  */
5594 static ResTreeNode *
5595 resource_tree_create (MonoArray *win32_resources)
5596 {
5597         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5598         GSList *l;
5599         int i;
5600
5601         tree = g_new0 (ResTreeNode, 1);
5602         
5603         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5604                 MonoReflectionWin32Resource *win32_res =
5605                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5606
5607                 /* Create node */
5608
5609                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5610                 lang_node = g_new0 (ResTreeNode, 1);
5611                 lang_node->id = win32_res->lang_id;
5612                 lang_node->win32_res = win32_res;
5613
5614                 /* Create type node if neccesary */
5615                 type_node = NULL;
5616                 for (l = tree->children; l; l = l->next)
5617                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5618                                 type_node = (ResTreeNode*)l->data;
5619                                 break;
5620                         }
5621
5622                 if (!type_node) {
5623                         type_node = g_new0 (ResTreeNode, 1);
5624                         type_node->id = win32_res->res_type;
5625
5626                         /* 
5627                          * The resource types have to be sorted otherwise
5628                          * Windows Explorer can't display the version information.
5629                          */
5630                         tree->children = g_slist_insert_sorted (tree->children, 
5631                                 type_node, resource_tree_compare_by_id);
5632                 }
5633
5634                 /* Create res node if neccesary */
5635                 res_node = NULL;
5636                 for (l = type_node->children; l; l = l->next)
5637                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5638                                 res_node = (ResTreeNode*)l->data;
5639                                 break;
5640                         }
5641
5642                 if (!res_node) {
5643                         res_node = g_new0 (ResTreeNode, 1);
5644                         res_node->id = win32_res->res_id;
5645                         type_node->children = g_slist_append (type_node->children, res_node);
5646                 }
5647
5648                 res_node->children = g_slist_append (res_node->children, lang_node);
5649         }
5650
5651         return tree;
5652 }
5653
5654 /*
5655  * resource_tree_encode:
5656  * 
5657  *   Encode the resource tree into the format used in the PE file.
5658  */
5659 static void
5660 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5661 {
5662         char *entries;
5663         MonoPEResourceDir dir;
5664         MonoPEResourceDirEntry dir_entry;
5665         MonoPEResourceDataEntry data_entry;
5666         GSList *l;
5667         guint32 res_id_entries;
5668
5669         /*
5670          * For the format of the resource directory, see the article
5671          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5672          * Matt Pietrek
5673          */
5674
5675         memset (&dir, 0, sizeof (dir));
5676         memset (&dir_entry, 0, sizeof (dir_entry));
5677         memset (&data_entry, 0, sizeof (data_entry));
5678
5679         g_assert (sizeof (dir) == 16);
5680         g_assert (sizeof (dir_entry) == 8);
5681         g_assert (sizeof (data_entry) == 16);
5682
5683         node->offset = p - begin;
5684
5685         /* IMAGE_RESOURCE_DIRECTORY */
5686         res_id_entries = g_slist_length (node->children);
5687         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5688
5689         memcpy (p, &dir, sizeof (dir));
5690         p += sizeof (dir);
5691
5692         /* Reserve space for entries */
5693         entries = p;
5694         p += sizeof (dir_entry) * res_id_entries;
5695
5696         /* Write children */
5697         for (l = node->children; l; l = l->next) {
5698                 ResTreeNode *child = (ResTreeNode*)l->data;
5699
5700                 if (child->win32_res) {
5701                         guint32 size;
5702
5703                         child->offset = p - begin;
5704
5705                         /* IMAGE_RESOURCE_DATA_ENTRY */
5706                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5707                         size = mono_array_length (child->win32_res->res_data);
5708                         data_entry.rde_size = GUINT32_TO_LE (size);
5709
5710                         memcpy (p, &data_entry, sizeof (data_entry));
5711                         p += sizeof (data_entry);
5712
5713                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5714                         p += size;
5715                 } else {
5716                         resource_tree_encode (child, begin, p, &p);
5717                 }
5718         }
5719
5720         /* IMAGE_RESOURCE_ENTRY */
5721         for (l = node->children; l; l = l->next) {
5722                 ResTreeNode *child = (ResTreeNode*)l->data;
5723
5724                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5725                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5726
5727                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5728                 entries += sizeof (dir_entry);
5729         }
5730
5731         *endbuf = p;
5732 }
5733
5734 static void
5735 resource_tree_free (ResTreeNode * node)
5736 {
5737         GSList * list;
5738         for (list = node->children; list; list = list->next)
5739                 resource_tree_free ((ResTreeNode*)list->data);
5740         g_slist_free(node->children);
5741         g_free (node);
5742 }
5743
5744 static void
5745 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5746 {
5747         char *buf;
5748         char *p;
5749         guint32 size, i;
5750         MonoReflectionWin32Resource *win32_res;
5751         ResTreeNode *tree;
5752
5753         if (!assemblyb->win32_resources)
5754                 return;
5755
5756         /*
5757          * Resources are stored in a three level tree inside the PE file.
5758          * - level one contains a node for each type of resource
5759          * - level two contains a node for each resource
5760          * - level three contains a node for each instance of a resource for a
5761          *   specific language.
5762          */
5763
5764         tree = resource_tree_create (assemblyb->win32_resources);
5765
5766         /* Estimate the size of the encoded tree */
5767         size = 0;
5768         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5769                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5770                 size += mono_array_length (win32_res->res_data);
5771         }
5772         /* Directory structure */
5773         size += mono_array_length (assemblyb->win32_resources) * 256;
5774         p = buf = g_malloc (size);
5775
5776         resource_tree_encode (tree, p, p, &p);
5777
5778         g_assert (p - buf <= size);
5779
5780         assembly->win32_res = g_malloc (p - buf);
5781         assembly->win32_res_size = p - buf;
5782         memcpy (assembly->win32_res, buf, p - buf);
5783
5784         g_free (buf);
5785         resource_tree_free (tree);
5786 }
5787
5788 static void
5789 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5790 {
5791         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5792         int i;
5793
5794         p += sizeof (MonoPEResourceDir);
5795         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5796                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5797                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5798                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5799                         fixup_resource_directory (res_section, child, rva);
5800                 } else {
5801                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5802                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5803                 }
5804
5805                 p += sizeof (MonoPEResourceDirEntry);
5806         }
5807 }
5808
5809 static void
5810 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5811 {
5812         guint32 dummy;
5813         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5814                 g_error ("WriteFile returned %d\n", GetLastError ());
5815 }
5816
5817 /*
5818  * mono_image_create_pefile:
5819  * @mb: a module builder object
5820  * 
5821  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5822  * assembly->pefile where it can be easily retrieved later in chunks.
5823  */
5824 void
5825 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5826 {
5827         MonoMSDOSHeader *msdos;
5828         MonoDotNetHeader *header;
5829         MonoSectionTable *section;
5830         MonoCLIHeader *cli_header;
5831         guint32 size, image_size, virtual_base, text_offset;
5832         guint32 header_start, section_start, file_offset, virtual_offset;
5833         MonoDynamicImage *assembly;
5834         MonoReflectionAssemblyBuilder *assemblyb;
5835         MonoDynamicStream pefile_stream = {0};
5836         MonoDynamicStream *pefile = &pefile_stream;
5837         int i, nsections;
5838         guint32 *rva, value;
5839         guchar *p;
5840         static const unsigned char msheader[] = {
5841                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5842                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5843                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5844                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5845                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5846                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5847                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5848                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5849         };
5850
5851         assemblyb = mb->assemblyb;
5852
5853         mono_image_basic_init (assemblyb);
5854         assembly = mb->dynamic_image;
5855
5856         assembly->pe_kind = assemblyb->pe_kind;
5857         assembly->machine = assemblyb->machine;
5858         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5859         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5860         
5861         mono_image_build_metadata (mb);
5862
5863         if (mb->is_main && assemblyb->resources) {
5864                 int len = mono_array_length (assemblyb->resources);
5865                 for (i = 0; i < len; ++i)
5866                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5867         }
5868
5869         if (mb->resources) {
5870                 int len = mono_array_length (mb->resources);
5871                 for (i = 0; i < len; ++i)
5872                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5873         }
5874
5875         build_compressed_metadata (assembly);
5876
5877         if (mb->is_main)
5878                 assembly_add_win32_resources (assembly, assemblyb);
5879
5880         nsections = calc_section_size (assembly);
5881         
5882         /* The DOS header and stub */
5883         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5884         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5885
5886         /* the dotnet header */
5887         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5888
5889         /* the section tables */
5890         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5891
5892         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5893         virtual_offset = VIRT_ALIGN;
5894         image_size = 0;
5895
5896         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5897                 if (!assembly->sections [i].size)
5898                         continue;
5899                 /* align offsets */
5900                 file_offset += FILE_ALIGN - 1;
5901                 file_offset &= ~(FILE_ALIGN - 1);
5902                 virtual_offset += VIRT_ALIGN - 1;
5903                 virtual_offset &= ~(VIRT_ALIGN - 1);
5904
5905                 assembly->sections [i].offset = file_offset;
5906                 assembly->sections [i].rva = virtual_offset;
5907
5908                 file_offset += assembly->sections [i].size;
5909                 virtual_offset += assembly->sections [i].size;
5910                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5911         }
5912
5913         file_offset += FILE_ALIGN - 1;
5914         file_offset &= ~(FILE_ALIGN - 1);
5915
5916         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5917
5918         /* back-patch info */
5919         msdos = (MonoMSDOSHeader*)pefile->data;
5920         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5921
5922         header = (MonoDotNetHeader*)(pefile->data + header_start);
5923         header->pesig [0] = 'P';
5924         header->pesig [1] = 'E';
5925         
5926         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5927         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5928         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5929         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5930         if (assemblyb->pekind == 1) {
5931                 /* it's a dll */
5932                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5933         } else {
5934                 /* it's an exe */
5935                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5936         }
5937
5938         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5939
5940         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5941         header->pe.pe_major = 6;
5942         header->pe.pe_minor = 0;
5943         size = assembly->sections [MONO_SECTION_TEXT].size;
5944         size += FILE_ALIGN - 1;
5945         size &= ~(FILE_ALIGN - 1);
5946         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5947         size = assembly->sections [MONO_SECTION_RSRC].size;
5948         size += FILE_ALIGN - 1;
5949         size &= ~(FILE_ALIGN - 1);
5950         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5951         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5952         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5953         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5954         /* pe_rva_entry_point always at the beginning of the text section */
5955         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5956
5957         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5958         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5959         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5960         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5961         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5962         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5963         size = section_start;
5964         size += FILE_ALIGN - 1;
5965         size &= ~(FILE_ALIGN - 1);
5966         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5967         size = image_size;
5968         size += VIRT_ALIGN - 1;
5969         size &= ~(VIRT_ALIGN - 1);
5970         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5971
5972         /*
5973         // Translate the PEFileKind value to the value expected by the Windows loader
5974         */
5975         {
5976                 short kind;
5977
5978                 /*
5979                 // PEFileKinds.Dll == 1
5980                 // PEFileKinds.ConsoleApplication == 2
5981                 // PEFileKinds.WindowApplication == 3
5982                 //
5983                 // need to get:
5984                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5985                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5986                 */
5987                 if (assemblyb->pekind == 3)
5988                         kind = 2;
5989                 else
5990                         kind = 3;
5991                 
5992                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5993         }    
5994         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5995         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5996         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5997         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5998         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5999         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6000
6001         /* fill data directory entries */
6002
6003         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6004         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6005
6006         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6007         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6008
6009         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6010         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6011         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6012         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6013         /* patch entrypoint name */
6014         if (assemblyb->pekind == 1)
6015                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6016         else
6017                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6018         /* patch imported function RVA name */
6019         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6020         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6021
6022         /* the import table */
6023         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6024         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6025         /* patch imported dll RVA name and other entries in the dir */
6026         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6027         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6028         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6029         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6030         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6031         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6032
6033         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6034         value = (assembly->text_rva + assembly->imp_names_offset);
6035         *p++ = (value) & 0xff;
6036         *p++ = (value >> 8) & (0xff);
6037         *p++ = (value >> 16) & (0xff);
6038         *p++ = (value >> 24) & (0xff);
6039
6040         /* the CLI header info */
6041         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6042         cli_header->ch_size = GUINT32_FROM_LE (72);
6043         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6044         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6045         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6046         if (assemblyb->entry_point) {
6047                 guint32 table_idx = 0;
6048                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6049                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6050                         table_idx = methodb->table_idx;
6051                 } else {
6052                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6053                 }
6054                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6055         } else {
6056                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6057         }
6058         /* The embedded managed resources */
6059         text_offset = assembly->text_rva + assembly->code.index;
6060         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6061         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6062         text_offset += assembly->resources.index;
6063         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6064         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6065         text_offset += assembly->meta_size;
6066         if (assembly->strong_name_size) {
6067                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6068                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6069                 text_offset += assembly->strong_name_size;
6070         }
6071
6072         /* write the section tables and section content */
6073         section = (MonoSectionTable*)(pefile->data + section_start);
6074         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6075                 static const char section_names [][7] = {
6076                         ".text", ".rsrc", ".reloc"
6077                 };
6078                 if (!assembly->sections [i].size)
6079                         continue;
6080                 strcpy (section->st_name, section_names [i]);
6081                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6082                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6083                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6084                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6085                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6086                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6087                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6088                 section ++;
6089         }
6090         
6091         checked_write_file (file, pefile->data, pefile->index);
6092         
6093         mono_dynamic_stream_reset (pefile);
6094         
6095         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6096                 if (!assembly->sections [i].size)
6097                         continue;
6098                 
6099                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6100                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6101                 
6102                 switch (i) {
6103                 case MONO_SECTION_TEXT:
6104                         /* patch entry point */
6105                         p = (guchar*)(assembly->code.data + 2);
6106                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6107                         *p++ = (value) & 0xff;
6108                         *p++ = (value >> 8) & 0xff;
6109                         *p++ = (value >> 16) & 0xff;
6110                         *p++ = (value >> 24) & 0xff;
6111                 
6112                         checked_write_file (file, assembly->code.data, assembly->code.index);
6113                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6114                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6115                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6116                                 
6117
6118                         g_free (assembly->image.raw_metadata);
6119                         break;
6120                 case MONO_SECTION_RELOC: {
6121                         struct {
6122                                 guint32 page_rva;
6123                                 guint32 block_size;
6124                                 guint16 type_and_offset;
6125                                 guint16 term;
6126                         } reloc;
6127                         
6128                         g_assert (sizeof (reloc) == 12);
6129                         
6130                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6131                         reloc.block_size = GUINT32_FROM_LE (12);
6132                         
6133                         /* 
6134                          * the entrypoint is always at the start of the text section 
6135                          * 3 is IMAGE_REL_BASED_HIGHLOW
6136                          * 2 is patch_size_rva - text_rva
6137                          */
6138                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6139                         reloc.term = 0;
6140                         
6141                         checked_write_file (file, &reloc, sizeof (reloc));
6142                         
6143                         break;
6144                 }
6145                 case MONO_SECTION_RSRC:
6146                         if (assembly->win32_res) {
6147
6148                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6149                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6150                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6151                         }
6152                         break;
6153                 default:
6154                         g_assert_not_reached ();
6155                 }
6156         }
6157         
6158         /* check that the file is properly padded */
6159         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6160                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6161         if (! SetEndOfFile (file))
6162                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6163         
6164         mono_dynamic_stream_reset (&assembly->code);
6165         mono_dynamic_stream_reset (&assembly->us);
6166         mono_dynamic_stream_reset (&assembly->blob);
6167         mono_dynamic_stream_reset (&assembly->guid);
6168         mono_dynamic_stream_reset (&assembly->sheap);
6169
6170         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6171         g_hash_table_destroy (assembly->blob_cache);
6172         assembly->blob_cache = NULL;
6173 }
6174
6175 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6176
6177 void
6178 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6179 {
6180         g_assert_not_reached ();
6181 }
6182
6183 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6184
6185 #ifndef DISABLE_REFLECTION_EMIT
6186
6187 MonoReflectionModule *
6188 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6189 {
6190         char *name;
6191         MonoImage *image;
6192         MonoImageOpenStatus status;
6193         MonoDynamicAssembly *assembly;
6194         guint32 module_count;
6195         MonoImage **new_modules;
6196         gboolean *new_modules_loaded;
6197         
6198         name = mono_string_to_utf8 (fileName);
6199
6200         image = mono_image_open (name, &status);
6201         if (!image) {
6202                 MonoException *exc;
6203                 if (status == MONO_IMAGE_ERROR_ERRNO)
6204                         exc = mono_get_exception_file_not_found (fileName);
6205                 else
6206                         exc = mono_get_exception_bad_image_format (name);
6207                 g_free (name);
6208                 mono_raise_exception (exc);
6209         }
6210
6211         g_free (name);
6212
6213         assembly = ab->dynamic_assembly;
6214         image->assembly = (MonoAssembly*)assembly;
6215
6216         module_count = image->assembly->image->module_count;
6217         new_modules = g_new0 (MonoImage *, module_count + 1);
6218         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6219
6220         if (image->assembly->image->modules)
6221                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6222         if (image->assembly->image->modules_loaded)
6223                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6224         new_modules [module_count] = image;
6225         new_modules_loaded [module_count] = TRUE;
6226         mono_image_addref (image);
6227
6228         g_free (image->assembly->image->modules);
6229         image->assembly->image->modules = new_modules;
6230         image->assembly->image->modules_loaded = new_modules_loaded;
6231         image->assembly->image->module_count ++;
6232
6233         mono_assembly_load_references (image, &status);
6234         if (status) {
6235                 mono_image_close (image);
6236                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6237         }
6238
6239         return mono_module_get_object (mono_domain_get (), image);
6240 }
6241
6242 #endif /* DISABLE_REFLECTION_EMIT */
6243
6244 /*
6245  * We need to return always the same object for MethodInfo, FieldInfo etc..
6246  * but we need to consider the reflected type.
6247  * type uses a different hash, since it uses custom hash/equal functions.
6248  */
6249
6250 typedef struct {
6251         gpointer item;
6252         MonoClass *refclass;
6253 } ReflectedEntry;
6254
6255 static gboolean
6256 reflected_equal (gconstpointer a, gconstpointer b) {
6257         const ReflectedEntry *ea = a;
6258         const ReflectedEntry *eb = b;
6259
6260         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6261 }
6262
6263 static guint
6264 reflected_hash (gconstpointer a) {
6265         const ReflectedEntry *ea = a;
6266         return mono_aligned_addr_hash (ea->item);
6267 }
6268
6269 #define CHECK_OBJECT(t,p,k)     \
6270         do {    \
6271                 t _obj; \
6272                 ReflectedEntry e;       \
6273                 e.item = (p);   \
6274                 e.refclass = (k);       \
6275                 mono_domain_lock (domain);      \
6276                 if (!domain->refobject_hash)    \
6277                         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");  \
6278                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6279                         mono_domain_unlock (domain);    \
6280                         return _obj;    \
6281                 }       \
6282         mono_domain_unlock (domain); \
6283         } while (0)
6284
6285 #ifdef HAVE_BOEHM_GC
6286 /* ReflectedEntry doesn't need to be GC tracked */
6287 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6288 #define FREE_REFENTRY(entry) g_free ((entry))
6289 #define REFENTRY_REQUIRES_CLEANUP
6290 #else
6291 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6292 /* FIXME: */
6293 #define FREE_REFENTRY(entry)
6294 #endif
6295
6296 #define CACHE_OBJECT(t,p,o,k)   \
6297         do {    \
6298                 t _obj; \
6299         ReflectedEntry pe; \
6300         pe.item = (p); \
6301         pe.refclass = (k); \
6302         mono_domain_lock (domain); \
6303                 if (!domain->refobject_hash)    \
6304                         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");  \
6305         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6306         if (!_obj) { \
6307                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6308                     e->item = (p);      \
6309                     e->refclass = (k);  \
6310                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6311             _obj = o; \
6312         } \
6313                 mono_domain_unlock (domain);    \
6314         return _obj; \
6315         } while (0)
6316
6317 static void
6318 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6319 {
6320         mono_domain_lock (domain);
6321         if (domain->refobject_hash) {
6322         ReflectedEntry pe;
6323                 gpointer orig_pe, orig_value;
6324
6325                 pe.item = o;
6326                 pe.refclass = klass;
6327                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6328                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6329                         FREE_REFENTRY (orig_pe);
6330                 }
6331         }
6332         mono_domain_unlock (domain);
6333 }
6334
6335 #ifdef REFENTRY_REQUIRES_CLEANUP
6336 static void
6337 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6338 {
6339         FREE_REFENTRY (key);
6340 }
6341 #endif
6342
6343 void
6344 mono_reflection_cleanup_domain (MonoDomain *domain)
6345 {
6346         if (domain->refobject_hash) {
6347 /*let's avoid scanning the whole hashtable if not needed*/
6348 #ifdef REFENTRY_REQUIRES_CLEANUP
6349                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6350 #endif
6351                 mono_g_hash_table_destroy (domain->refobject_hash);
6352                 domain->refobject_hash = NULL;
6353         }
6354 }
6355
6356 #ifndef DISABLE_REFLECTION_EMIT
6357 static gpointer
6358 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6359 {
6360         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6361 }
6362
6363 static gpointer
6364 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6365 {
6366         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6367 }
6368
6369 void
6370 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6371 {
6372         MonoDynamicImage *image = moduleb->dynamic_image;
6373         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6374         if (!image) {
6375                 MonoError error;
6376                 int module_count;
6377                 MonoImage **new_modules;
6378                 MonoImage *ass;
6379                 char *name, *fqname;
6380                 /*
6381                  * FIXME: we already created an image in mono_image_basic_init (), but
6382                  * we don't know which module it belongs to, since that is only 
6383                  * determined at assembly save time.
6384                  */
6385                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6386                 name = mono_string_to_utf8 (ab->name);
6387                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6388                 if (!mono_error_ok (&error)) {
6389                         g_free (name);
6390                         mono_error_raise_exception (&error);
6391                 }
6392                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6393
6394                 moduleb->module.image = &image->image;
6395                 moduleb->dynamic_image = image;
6396                 register_module (mono_object_domain (moduleb), moduleb, image);
6397
6398                 /* register the module with the assembly */
6399                 ass = ab->dynamic_assembly->assembly.image;
6400                 module_count = ass->module_count;
6401                 new_modules = g_new0 (MonoImage *, module_count + 1);
6402
6403                 if (ass->modules)
6404                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6405                 new_modules [module_count] = &image->image;
6406                 mono_image_addref (&image->image);
6407
6408                 g_free (ass->modules);
6409                 ass->modules = new_modules;
6410                 ass->module_count ++;
6411         }
6412 }
6413
6414 void
6415 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6416 {
6417         MonoDynamicImage *image = moduleb->dynamic_image;
6418
6419         g_assert (type->type);
6420         image->wrappers_type = mono_class_from_mono_type (type->type);
6421 }
6422
6423 #endif
6424
6425 /*
6426  * mono_assembly_get_object:
6427  * @domain: an app domain
6428  * @assembly: an assembly
6429  *
6430  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6431  */
6432 MonoReflectionAssembly*
6433 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6434 {
6435         static MonoClass *assembly_type;
6436         MonoReflectionAssembly *res;
6437         
6438         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6439         if (!assembly_type) {
6440                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6441                 if (klass == NULL)
6442                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6443                 g_assert (klass);
6444                 assembly_type = klass;
6445         }
6446         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6447         res->assembly = assembly;
6448
6449         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6450 }
6451
6452
6453
6454 MonoReflectionModule*   
6455 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6456 {
6457         static MonoClass *module_type;
6458         MonoReflectionModule *res;
6459         char* basename;
6460         
6461         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6462         if (!module_type) {
6463                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6464                 if (klass == NULL)
6465                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6466                 g_assert (klass);
6467                 module_type = klass;
6468         }
6469         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6470
6471         res->image = image;
6472         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6473
6474         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6475         basename = g_path_get_basename (image->name);
6476         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6477         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6478         
6479         g_free (basename);
6480
6481         if (image->assembly->image == image) {
6482                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6483         } else {
6484                 int i;
6485                 res->token = 0;
6486                 if (image->assembly->image->modules) {
6487                         for (i = 0; i < image->assembly->image->module_count; i++) {
6488                                 if (image->assembly->image->modules [i] == image)
6489                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6490                         }
6491                         g_assert (res->token);
6492                 }
6493         }
6494
6495         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6496 }
6497
6498 MonoReflectionModule*   
6499 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6500 {
6501         static MonoClass *module_type;
6502         MonoReflectionModule *res;
6503         MonoTableInfo *table;
6504         guint32 cols [MONO_FILE_SIZE];
6505         const char *name;
6506         guint32 i, name_idx;
6507         const char *val;
6508         
6509         if (!module_type) {
6510                 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6511                 if (klass == NULL)
6512                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6513                 g_assert (klass);
6514                 module_type = klass;
6515         }
6516         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6517
6518         table = &image->tables [MONO_TABLE_FILE];
6519         g_assert (table_index < table->rows);
6520         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6521
6522         res->image = NULL;
6523         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6524         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6525
6526         /* Check whenever the row has a corresponding row in the moduleref table */
6527         table = &image->tables [MONO_TABLE_MODULEREF];
6528         for (i = 0; i < table->rows; ++i) {
6529                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6530                 val = mono_metadata_string_heap (image, name_idx);
6531                 if (strcmp (val, name) == 0)
6532                         res->image = image->modules [i];
6533         }
6534
6535         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6536         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6537         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6538         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6539         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6540
6541         return res;
6542 }
6543
6544 static gboolean
6545 verify_safe_for_managed_space (MonoType *type)
6546 {
6547         switch (type->type) {
6548 #ifdef DEBUG_HARDER
6549         case MONO_TYPE_ARRAY:
6550                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6551         case MONO_TYPE_PTR:
6552                 return verify_safe_for_managed_space (type->data.type);
6553         case MONO_TYPE_SZARRAY:
6554                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6555         case MONO_TYPE_GENERICINST: {
6556                 MonoGenericInst *inst = type->data.generic_class->inst;
6557                 int i;
6558                 if (!inst->is_open)
6559                         break;
6560                 for (i = 0; i < inst->type_argc; ++i)
6561                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6562                                 return FALSE;
6563                 return TRUE;
6564         }
6565 #endif
6566         case MONO_TYPE_VAR:
6567         case MONO_TYPE_MVAR:
6568                 return TRUE;
6569         default:
6570                 return TRUE;
6571         }
6572 }
6573
6574 static MonoType*
6575 mono_type_normalize (MonoType *type)
6576 {
6577         int i;
6578         MonoGenericClass *gclass;
6579         MonoGenericInst *ginst;
6580         MonoClass *gtd;
6581         MonoGenericContainer *gcontainer;
6582         MonoType **argv = NULL;
6583         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6584
6585         if (type->type != MONO_TYPE_GENERICINST)
6586                 return type;
6587
6588         gclass = type->data.generic_class;
6589         ginst = gclass->context.class_inst;
6590         if (!ginst->is_open)
6591                 return type;
6592
6593         gtd = gclass->container_class;
6594         gcontainer = gtd->generic_container;
6595         argv = g_newa (MonoType*, ginst->type_argc);
6596
6597         for (i = 0; i < ginst->type_argc; ++i) {
6598                 MonoType *t = ginst->type_argv [i], *norm;
6599                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6600                         is_denorm_gtd = FALSE;
6601                 norm = mono_type_normalize (t);
6602                 argv [i] = norm;
6603                 if (norm != t)
6604                         requires_rebind = TRUE;
6605         }
6606
6607         if (is_denorm_gtd)
6608                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6609
6610         if (requires_rebind) {
6611                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6612                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6613         }
6614
6615         return type;
6616 }
6617 /*
6618  * mono_type_get_object:
6619  * @domain: an app domain
6620  * @type: a type
6621  *
6622  * Return an System.MonoType object representing the type @type.
6623  */
6624 MonoReflectionType*
6625 mono_type_get_object (MonoDomain *domain, MonoType *type)
6626 {
6627         MonoType *norm_type;
6628         MonoReflectionType *res;
6629         MonoClass *klass = mono_class_from_mono_type (type);
6630
6631         /*we must avoid using @type as it might have come
6632          * from a mono_metadata_type_dup and the caller
6633          * expects that is can be freed.
6634          * Using the right type from 
6635          */
6636         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6637
6638         /* void is very common */
6639         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6640                 return (MonoReflectionType*)domain->typeof_void;
6641
6642         /*
6643          * If the vtable of the given class was already created, we can use
6644          * the MonoType from there and avoid all locking and hash table lookups.
6645          * 
6646          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6647          * that the resulting object is different.   
6648          */
6649         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6650                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6651                 if (vtable && vtable->type)
6652                         return vtable->type;
6653         }
6654
6655         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6656         mono_domain_lock (domain);
6657         if (!domain->type_hash)
6658                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6659                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6660         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6661                 mono_domain_unlock (domain);
6662                 mono_loader_unlock ();
6663                 return res;
6664         }
6665
6666         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6667          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6668          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6669          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6670          * artifact of how generics are encoded and should be transparent to managed code so we
6671          * need to weed out this diference when retrieving managed System.Type objects.
6672          */
6673         norm_type = mono_type_normalize (type);
6674         if (norm_type != type) {
6675                 res = mono_type_get_object (domain, norm_type);
6676                 mono_g_hash_table_insert (domain->type_hash, type, res);
6677                 mono_domain_unlock (domain);
6678                 mono_loader_unlock ();
6679                 return res;
6680         }
6681
6682         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6683         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6684                 g_assert (0);
6685
6686         if (!verify_safe_for_managed_space (type)) {
6687                 mono_domain_unlock (domain);
6688                 mono_loader_unlock ();
6689                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6690         }
6691
6692         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6693                 gboolean is_type_done = TRUE;
6694                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6695                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6696                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6697                 */
6698                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6699                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6700
6701                         if (gparam->owner && gparam->owner->is_method) {
6702                                 MonoMethod *method = gparam->owner->owner.method;
6703                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6704                                         is_type_done = FALSE;
6705                         } else if (gparam->owner && !gparam->owner->is_method) {
6706                                 MonoClass *klass = gparam->owner->owner.klass;
6707                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6708                                         is_type_done = FALSE;
6709                         }
6710                 } 
6711
6712                 /* g_assert_not_reached (); */
6713                 /* should this be considered an error condition? */
6714                 if (is_type_done && !type->byref) {
6715                         mono_domain_unlock (domain);
6716                         mono_loader_unlock ();
6717                         return mono_class_get_ref_info (klass);
6718                 }
6719         }
6720         /* This is stored in vtables/JITted code so it has to be pinned */
6721         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6722         res->type = type;
6723         mono_g_hash_table_insert (domain->type_hash, type, res);
6724
6725         if (type->type == MONO_TYPE_VOID)
6726                 domain->typeof_void = (MonoObject*)res;
6727
6728         mono_domain_unlock (domain);
6729         mono_loader_unlock ();
6730         return res;
6731 }
6732
6733 /*
6734  * mono_method_get_object:
6735  * @domain: an app domain
6736  * @method: a method
6737  * @refclass: the reflected type (can be NULL)
6738  *
6739  * Return an System.Reflection.MonoMethod object representing the method @method.
6740  */
6741 MonoReflectionMethod*
6742 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6743 {
6744         /*
6745          * We use the same C representation for methods and constructors, but the type 
6746          * name in C# is different.
6747          */
6748         static MonoClass *System_Reflection_MonoMethod = NULL;
6749         static MonoClass *System_Reflection_MonoCMethod = NULL;
6750         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6751         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6752         MonoClass *klass;
6753         MonoReflectionMethod *ret;
6754
6755         if (method->is_inflated) {
6756                 MonoReflectionGenericMethod *gret;
6757
6758                 refclass = method->klass;
6759                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6760                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6761                         if (!System_Reflection_MonoGenericCMethod)
6762                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6763                         klass = System_Reflection_MonoGenericCMethod;
6764                 } else {
6765                         if (!System_Reflection_MonoGenericMethod)
6766                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6767                         klass = System_Reflection_MonoGenericMethod;
6768                 }
6769                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6770                 gret->method.method = method;
6771                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6772                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6773                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6774         }
6775
6776         if (!refclass)
6777                 refclass = method->klass;
6778
6779         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6780         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6781                 if (!System_Reflection_MonoCMethod)
6782                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6783                 klass = System_Reflection_MonoCMethod;
6784         }
6785         else {
6786                 if (!System_Reflection_MonoMethod)
6787                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6788                 klass = System_Reflection_MonoMethod;
6789         }
6790         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6791         ret->method = method;
6792         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6793         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6794 }
6795
6796 /*
6797  * mono_method_clear_object:
6798  *
6799  *   Clear the cached reflection objects for the dynamic method METHOD.
6800  */
6801 void
6802 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6803 {
6804         MonoClass *klass;
6805         g_assert (method_is_dynamic (method));
6806
6807         klass = method->klass;
6808         while (klass) {
6809                 clear_cached_object (domain, method, klass);
6810                 klass = klass->parent;
6811         }
6812         /* Added by mono_param_get_objects () */
6813         clear_cached_object (domain, &(method->signature), NULL);
6814         klass = method->klass;
6815         while (klass) {
6816                 clear_cached_object (domain, &(method->signature), klass);
6817                 klass = klass->parent;
6818         }
6819 }
6820
6821 /*
6822  * mono_field_get_object:
6823  * @domain: an app domain
6824  * @klass: a type
6825  * @field: a field
6826  *
6827  * Return an System.Reflection.MonoField object representing the field @field
6828  * in class @klass.
6829  */
6830 MonoReflectionField*
6831 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6832 {
6833         MonoReflectionField *res;
6834         static MonoClass *monofield_klass;
6835
6836         CHECK_OBJECT (MonoReflectionField *, field, klass);
6837         if (!monofield_klass)
6838                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6839         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6840         res->klass = klass;
6841         res->field = field;
6842         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6843
6844         if (is_field_on_inst (field)) {
6845                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6846                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6847         } else {
6848                 if (field->type)
6849                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6850                 res->attrs = mono_field_get_flags (field);
6851         }
6852         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6853 }
6854
6855 /*
6856  * mono_property_get_object:
6857  * @domain: an app domain
6858  * @klass: a type
6859  * @property: a property
6860  *
6861  * Return an System.Reflection.MonoProperty object representing the property @property
6862  * in class @klass.
6863  */
6864 MonoReflectionProperty*
6865 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6866 {
6867         MonoReflectionProperty *res;
6868         static MonoClass *monoproperty_klass;
6869
6870         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6871         if (!monoproperty_klass)
6872                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6873         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6874         res->klass = klass;
6875         res->property = property;
6876         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6877 }
6878
6879 /*
6880  * mono_event_get_object:
6881  * @domain: an app domain
6882  * @klass: a type
6883  * @event: a event
6884  *
6885  * Return an System.Reflection.MonoEvent object representing the event @event
6886  * in class @klass.
6887  */
6888 MonoReflectionEvent*
6889 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6890 {
6891         MonoReflectionEvent *res;
6892         MonoReflectionMonoEvent *mono_event;
6893         static MonoClass *monoevent_klass;
6894
6895         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6896         if (!monoevent_klass)
6897                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6898         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6899         mono_event->klass = klass;
6900         mono_event->event = event;
6901         res = (MonoReflectionEvent*)mono_event;
6902         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6903 }
6904
6905 /**
6906  * mono_get_reflection_missing_object:
6907  * @domain: Domain where the object lives
6908  *
6909  * Returns the System.Reflection.Missing.Value singleton object
6910  * (of type System.Reflection.Missing).
6911  *
6912  * Used as the value for ParameterInfo.DefaultValue when Optional
6913  * is present
6914  */
6915 static MonoObject *
6916 mono_get_reflection_missing_object (MonoDomain *domain)
6917 {
6918         MonoObject *obj;
6919         static MonoClassField *missing_value_field = NULL;
6920         
6921         if (!missing_value_field) {
6922                 MonoClass *missing_klass;
6923                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6924                 mono_class_init (missing_klass);
6925                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6926                 g_assert (missing_value_field);
6927         }
6928         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6929         g_assert (obj);
6930         return obj;
6931 }
6932
6933 static MonoObject*
6934 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6935 {
6936         if (!*dbnull)
6937                 *dbnull = mono_get_dbnull_object (domain);
6938         return *dbnull;
6939 }
6940
6941 static MonoObject*
6942 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6943 {
6944         if (!*reflection_missing)
6945                 *reflection_missing = mono_get_reflection_missing_object (domain);
6946         return *reflection_missing;
6947 }
6948
6949 /*
6950  * mono_param_get_objects:
6951  * @domain: an app domain
6952  * @method: a method
6953  *
6954  * Return an System.Reflection.ParameterInfo array object representing the parameters
6955  * in the method @method.
6956  */
6957 MonoArray*
6958 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6959 {
6960         static MonoClass *System_Reflection_ParameterInfo;
6961         static MonoClass *System_Reflection_ParameterInfo_array;
6962         MonoError error;
6963         MonoArray *res = NULL;
6964         MonoReflectionMethod *member = NULL;
6965         MonoReflectionParameter *param = NULL;
6966         char **names, **blobs = NULL;
6967         guint32 *types = NULL;
6968         MonoType *type = NULL;
6969         MonoObject *dbnull = NULL;
6970         MonoObject *missing = NULL;
6971         MonoMarshalSpec **mspecs;
6972         MonoMethodSignature *sig;
6973         MonoVTable *pinfo_vtable;
6974         int i;
6975
6976         if (!System_Reflection_ParameterInfo_array) {
6977                 MonoClass *klass;
6978
6979                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6980                 if (!klass)
6981                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6982
6983                 mono_memory_barrier ();
6984                 System_Reflection_ParameterInfo = klass; 
6985
6986         
6987                 klass = mono_array_class_get (klass, 1);
6988                 mono_memory_barrier ();
6989                 System_Reflection_ParameterInfo_array = klass;
6990         }
6991
6992         sig = mono_method_signature_checked (method, &error);
6993         if (!mono_error_ok (&error))
6994                 mono_error_raise_exception (&error);
6995
6996         if (!sig->param_count)
6997                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6998
6999         /* Note: the cache is based on the address of the signature into the method
7000          * since we already cache MethodInfos with the method as keys.
7001          */
7002         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7003
7004         member = mono_method_get_object (domain, method, refclass);
7005         names = g_new (char *, sig->param_count);
7006         mono_method_get_param_names (method, (const char **) names);
7007
7008         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7009         mono_method_get_marshal_info (method, mspecs);
7010
7011         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
7012         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7013         for (i = 0; i < sig->param_count; ++i) {
7014                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
7015                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7016                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7017                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7018                 param->PositionImpl = i;
7019                 param->AttrsImpl = sig->params [i]->attrs;
7020
7021                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7022                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7023                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7024                         else
7025                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7026                 } else {
7027
7028                         if (!blobs) {
7029                                 blobs = g_new0 (char *, sig->param_count);
7030                                 types = g_new0 (guint32, sig->param_count);
7031                                 get_default_param_value_blobs (method, blobs, types); 
7032                         }
7033
7034                         /* Build MonoType for the type from the Constant Table */
7035                         if (!type)
7036                                 type = g_new0 (MonoType, 1);
7037                         type->type = types [i];
7038                         type->data.klass = NULL;
7039                         if (types [i] == MONO_TYPE_CLASS)
7040                                 type->data.klass = mono_defaults.object_class;
7041                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7042                                 /* For enums, types [i] contains the base type */
7043
7044                                         type->type = MONO_TYPE_VALUETYPE;
7045                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7046                         } else
7047                                 type->data.klass = mono_class_from_mono_type (type);
7048
7049                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7050
7051                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7052                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7053                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7054                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7055                                 else
7056                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7057                         }
7058                         
7059                 }
7060
7061                 if (mspecs [i + 1])
7062                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7063                 
7064                 mono_array_setref (res, i, param);
7065         }
7066         g_free (names);
7067         g_free (blobs);
7068         g_free (types);
7069         g_free (type);
7070
7071         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7072                 if (mspecs [i])
7073                         mono_metadata_free_marshal_spec (mspecs [i]);
7074         g_free (mspecs);
7075         
7076         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7077 }
7078
7079 MonoArray*
7080 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7081 {
7082         return mono_param_get_objects_internal (domain, method, NULL);
7083 }
7084
7085 /*
7086  * mono_method_body_get_object:
7087  * @domain: an app domain
7088  * @method: a method
7089  *
7090  * Return an System.Reflection.MethodBody object representing the method @method.
7091  */
7092 MonoReflectionMethodBody*
7093 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7094 {
7095         static MonoClass *System_Reflection_MethodBody = NULL;
7096         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7097         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7098         MonoReflectionMethodBody *ret;
7099         MonoMethodHeader *header;
7100         MonoImage *image;
7101         guint32 method_rva, local_var_sig_token;
7102     char *ptr;
7103         unsigned char format, flags;
7104         int i;
7105
7106         /* for compatibility with .net */
7107     if (method_is_dynamic (method))
7108         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7109
7110         if (!System_Reflection_MethodBody)
7111                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7112         if (!System_Reflection_LocalVariableInfo)
7113                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7114         if (!System_Reflection_ExceptionHandlingClause)
7115                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7116
7117         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7118
7119         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7120                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7121             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7122                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7123             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7124                 return NULL;
7125
7126         image = method->klass->image;
7127         header = mono_method_get_header (method);
7128
7129         if (!image_is_dynamic (image)) {
7130                 /* Obtain local vars signature token */
7131                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7132                 ptr = mono_image_rva_map (image, method_rva);
7133                 flags = *(const unsigned char *) ptr;
7134                 format = flags & METHOD_HEADER_FORMAT_MASK;
7135                 switch (format){
7136                 case METHOD_HEADER_TINY_FORMAT:
7137                         local_var_sig_token = 0;
7138                         break;
7139                 case METHOD_HEADER_FAT_FORMAT:
7140                         ptr += 2;
7141                         ptr += 2;
7142                         ptr += 4;
7143                         local_var_sig_token = read32 (ptr);
7144                         break;
7145                 default:
7146                         g_assert_not_reached ();
7147                 }
7148         } else
7149                 local_var_sig_token = 0; //FIXME
7150
7151         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7152
7153         ret->init_locals = header->init_locals;
7154         ret->max_stack = header->max_stack;
7155         ret->local_var_sig_token = local_var_sig_token;
7156         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7157         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7158
7159         /* Locals */
7160         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7161         for (i = 0; i < header->num_locals; ++i) {
7162                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7163                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7164                 info->is_pinned = header->locals [i]->pinned;
7165                 info->local_index = i;
7166                 mono_array_setref (ret->locals, i, info);
7167         }
7168
7169         /* Exceptions */
7170         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7171         for (i = 0; i < header->num_clauses; ++i) {
7172                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7173                 MonoExceptionClause *clause = &header->clauses [i];
7174
7175                 info->flags = clause->flags;
7176                 info->try_offset = clause->try_offset;
7177                 info->try_length = clause->try_len;
7178                 info->handler_offset = clause->handler_offset;
7179                 info->handler_length = clause->handler_len;
7180                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7181                         info->filter_offset = clause->data.filter_offset;
7182                 else if (clause->data.catch_class)
7183                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7184
7185                 mono_array_setref (ret->clauses, i, info);
7186         }
7187
7188         mono_metadata_free_mh (header);
7189         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7190         return ret;
7191 }
7192
7193 /**
7194  * mono_get_dbnull_object:
7195  * @domain: Domain where the object lives
7196  *
7197  * Returns the System.DBNull.Value singleton object
7198  *
7199  * Used as the value for ParameterInfo.DefaultValue 
7200  */
7201 MonoObject *
7202 mono_get_dbnull_object (MonoDomain *domain)
7203 {
7204         MonoObject *obj;
7205         static MonoClassField *dbnull_value_field = NULL;
7206         
7207         if (!dbnull_value_field) {
7208                 MonoClass *dbnull_klass;
7209                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7210                 mono_class_init (dbnull_klass);
7211                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7212                 g_assert (dbnull_value_field);
7213         }
7214         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7215         g_assert (obj);
7216         return obj;
7217 }
7218
7219 static void
7220 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7221 {
7222         guint32 param_index, i, lastp, crow = 0;
7223         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7224         gint32 idx;
7225
7226         MonoClass *klass = method->klass;
7227         MonoImage *image = klass->image;
7228         MonoMethodSignature *methodsig = mono_method_signature (method);
7229
7230         MonoTableInfo *constt;
7231         MonoTableInfo *methodt;
7232         MonoTableInfo *paramt;
7233
7234         if (!methodsig->param_count)
7235                 return;
7236
7237         mono_class_init (klass);
7238
7239         if (image_is_dynamic (klass->image)) {
7240                 MonoReflectionMethodAux *aux;
7241                 if (method->is_inflated)
7242                         method = ((MonoMethodInflated*)method)->declaring;
7243                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7244                 if (aux && aux->param_defaults) {
7245                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7246                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7247                 }
7248                 return;
7249         }
7250
7251         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7252         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7253         constt = &image->tables [MONO_TABLE_CONSTANT];
7254
7255         idx = mono_method_get_index (method) - 1;
7256         g_assert (idx != -1);
7257
7258         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7259         if (idx + 1 < methodt->rows)
7260                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7261         else
7262                 lastp = paramt->rows + 1;
7263
7264         for (i = param_index; i < lastp; ++i) {
7265                 guint32 paramseq;
7266
7267                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7268                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7269
7270                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7271                         continue;
7272
7273                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7274                 if (!crow) {
7275                         continue;
7276                 }
7277         
7278                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7279                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7280                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7281         }
7282
7283         return;
7284 }
7285
7286 MonoObject *
7287 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7288 {
7289         void *retval;
7290         MonoClass *klass;
7291         MonoObject *object;
7292         MonoType *basetype = type;
7293
7294         if (!blob)
7295                 return NULL;
7296         
7297         klass = mono_class_from_mono_type (type);
7298         if (klass->valuetype) {
7299                 object = mono_object_new (domain, klass);
7300                 retval = ((gchar *) object + sizeof (MonoObject));
7301                 if (klass->enumtype)
7302                         basetype = mono_class_enum_basetype (klass);
7303         } else {
7304                 retval = &object;
7305         }
7306                         
7307         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7308                 return object;
7309         else
7310                 return NULL;
7311 }
7312
7313 static int
7314 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7315         int found_sep;
7316         char *s;
7317         gboolean quoted = FALSE;
7318
7319         memset (assembly, 0, sizeof (MonoAssemblyName));
7320         assembly->culture = "";
7321         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7322
7323         if (*p == '"') {
7324                 quoted = TRUE;
7325                 p++;
7326         }
7327         assembly->name = p;
7328         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7329                 p++;
7330         if (quoted) {
7331                 if (*p != '"')
7332                         return 1;
7333                 *p = 0;
7334                 p++;
7335         }
7336         if (*p != ',')
7337                 return 1;
7338         *p = 0;
7339         /* Remove trailing whitespace */
7340         s = p - 1;
7341         while (*s && g_ascii_isspace (*s))
7342                 *s-- = 0;
7343         p ++;
7344         while (g_ascii_isspace (*p))
7345                 p++;
7346         while (*p) {
7347                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7348                         p += 8;
7349                         assembly->major = strtoul (p, &s, 10);
7350                         if (s == p || *s != '.')
7351                                 return 1;
7352                         p = ++s;
7353                         assembly->minor = strtoul (p, &s, 10);
7354                         if (s == p || *s != '.')
7355                                 return 1;
7356                         p = ++s;
7357                         assembly->build = strtoul (p, &s, 10);
7358                         if (s == p || *s != '.')
7359                                 return 1;
7360                         p = ++s;
7361                         assembly->revision = strtoul (p, &s, 10);
7362                         if (s == p)
7363                                 return 1;
7364                         p = s;
7365                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7366                         p += 8;
7367                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7368                                 assembly->culture = "";
7369                                 p += 7;
7370                         } else {
7371                                 assembly->culture = p;
7372                                 while (*p && *p != ',') {
7373                                         p++;
7374                                 }
7375                         }
7376                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7377                         p += 15;
7378                         if (strncmp (p, "null", 4) == 0) {
7379                                 p += 4;
7380                         } else {
7381                                 int len;
7382                                 gchar *start = p;
7383                                 while (*p && *p != ',') {
7384                                         p++;
7385                                 }
7386                                 len = (p - start + 1);
7387                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7388                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7389                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7390                         }
7391                 } else {
7392                         while (*p && *p != ',')
7393                                 p++;
7394                 }
7395                 found_sep = 0;
7396                 while (g_ascii_isspace (*p) || *p == ',') {
7397                         *p++ = 0;
7398                         found_sep = 1;
7399                         continue;
7400                 }
7401                 /* failed */
7402                 if (!found_sep)
7403                         return 1;
7404         }
7405
7406         return 0;
7407 }
7408
7409 /*
7410  * mono_reflection_parse_type:
7411  * @name: type name
7412  *
7413  * Parse a type name as accepted by the GetType () method and output the info
7414  * extracted in the info structure.
7415  * the name param will be mangled, so, make a copy before passing it to this function.
7416  * The fields in info will be valid until the memory pointed to by name is valid.
7417  *
7418  * See also mono_type_get_name () below.
7419  *
7420  * Returns: 0 on parse error.
7421  */
7422 static int
7423 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7424                              MonoTypeNameParse *info)
7425 {
7426         char *start, *p, *w, *last_point, *startn;
7427         int in_modifiers = 0;
7428         int isbyref = 0, rank = 0, isptr = 0;
7429
7430         start = p = w = name;
7431
7432         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7433         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7434         info->name = info->name_space = NULL;
7435         info->nested = NULL;
7436         info->modifiers = NULL;
7437         info->type_arguments = NULL;
7438
7439         /* last_point separates the namespace from the name */
7440         last_point = NULL;
7441         /* Skips spaces */
7442         while (*p == ' ') p++, start++, w++, name++;
7443
7444         while (*p) {
7445                 switch (*p) {
7446                 case '+':
7447                         *p = 0; /* NULL terminate the name */
7448                         startn = p + 1;
7449                         info->nested = g_list_append (info->nested, startn);
7450                         /* we have parsed the nesting namespace + name */
7451                         if (info->name)
7452                                 break;
7453                         if (last_point) {
7454                                 info->name_space = start;
7455                                 *last_point = 0;
7456                                 info->name = last_point + 1;
7457                         } else {
7458                                 info->name_space = (char *)"";
7459                                 info->name = start;
7460                         }
7461                         break;
7462                 case '.':
7463                         last_point = p;
7464                         break;
7465                 case '\\':
7466                         ++p;
7467                         break;
7468                 case '&':
7469                 case '*':
7470                 case '[':
7471                 case ',':
7472                 case ']':
7473                         in_modifiers = 1;
7474                         break;
7475                 default:
7476                         break;
7477                 }
7478                 if (in_modifiers)
7479                         break;
7480                 // *w++ = *p++;
7481                 p++;
7482         }
7483         
7484         if (!info->name) {
7485                 if (last_point) {
7486                         info->name_space = start;
7487                         *last_point = 0;
7488                         info->name = last_point + 1;
7489                 } else {
7490                         info->name_space = (char *)"";
7491                         info->name = start;
7492                 }
7493         }
7494         while (*p) {
7495                 switch (*p) {
7496                 case '&':
7497                         if (isbyref) /* only one level allowed by the spec */
7498                                 return 0;
7499                         isbyref = 1;
7500                         isptr = 0;
7501                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7502                         *p++ = 0;
7503                         break;
7504                 case '*':
7505                         if (isbyref) /* pointer to ref not okay */
7506                                 return 0;
7507                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7508                         isptr = 1;
7509                         *p++ = 0;
7510                         break;
7511                 case '[':
7512                         if (isbyref) /* array of ref and generic ref are not okay */
7513                                 return 0;
7514                         //Decide if it's an array of a generic argument list
7515                         *p++ = 0;
7516
7517                         if (!*p) //XXX test
7518                                 return 0;
7519                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7520                                 isptr = 0;
7521                                 rank = 1;
7522                                 while (*p) {
7523                                         if (*p == ']')
7524                                                 break;
7525                                         if (*p == ',')
7526                                                 rank++;
7527                                         else if (*p == '*') /* '*' means unknown lower bound */
7528                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7529                                         else
7530                                                 return 0;
7531                                         ++p;
7532                                 }
7533                                 if (*p++ != ']')
7534                                         return 0;
7535                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7536                         } else {
7537                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7538                                         return 0;
7539                                 isptr = 0;
7540                                 info->type_arguments = g_ptr_array_new ();
7541                                 while (*p) {
7542                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7543                                         gboolean fqname = FALSE;
7544
7545                                         g_ptr_array_add (info->type_arguments, subinfo);
7546
7547                                         while (*p == ' ') p++;
7548                                         if (*p == '[') {
7549                                                 p++;
7550                                                 fqname = TRUE;
7551                                         }
7552
7553                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7554                                                 return 0;
7555
7556                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7557                                         if (fqname && (*p != ']')) {
7558                                                 char *aname;
7559
7560                                                 if (*p != ',')
7561                                                         return 0;
7562                                                 *p++ = 0;
7563
7564                                                 aname = p;
7565                                                 while (*p && (*p != ']'))
7566                                                         p++;
7567
7568                                                 if (*p != ']')
7569                                                         return 0;
7570
7571                                                 *p++ = 0;
7572                                                 while (*aname) {
7573                                                         if (g_ascii_isspace (*aname)) {
7574                                                                 ++aname;
7575                                                                 continue;
7576                                                         }
7577                                                         break;
7578                                                 }
7579                                                 if (!*aname ||
7580                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7581                                                         return 0;
7582                                         } else if (fqname && (*p == ']')) {
7583                                                 *p++ = 0;
7584                                         }
7585                                         if (*p == ']') {
7586                                                 *p++ = 0;
7587                                                 break;
7588                                         } else if (!*p) {
7589                                                 return 0;
7590                                         }
7591                                         *p++ = 0;
7592                                 }
7593                         }
7594                         break;
7595                 case ']':
7596                         if (is_recursed)
7597                                 goto end;
7598                         return 0;
7599                 case ',':
7600                         if (is_recursed)
7601                                 goto end;
7602                         *p++ = 0;
7603                         while (*p) {
7604                                 if (g_ascii_isspace (*p)) {
7605                                         ++p;
7606                                         continue;
7607                                 }
7608                                 break;
7609                         }
7610                         if (!*p)
7611                                 return 0; /* missing assembly name */
7612                         if (!assembly_name_to_aname (&info->assembly, p))
7613                                 return 0;
7614                         break;
7615                 default:
7616                         return 0;
7617                 }
7618                 if (info->assembly.name)
7619                         break;
7620         }
7621         // *w = 0; /* terminate class name */
7622  end:
7623         if (!info->name || !*info->name)
7624                 return 0;
7625         if (endptr)
7626                 *endptr = p;
7627         /* add other consistency checks */
7628         return 1;
7629 }
7630
7631
7632 /**
7633  * mono_identifier_unescape_type_name_chars:
7634  * @identifier: the display name of a mono type
7635  *
7636  * Returns:
7637  *  The name in internal form, that is without escaping backslashes.
7638  *
7639  *  The string is modified in place!
7640  */
7641 char*
7642 mono_identifier_unescape_type_name_chars(char* identifier)
7643 {
7644         char *w, *r;
7645         if (!identifier)
7646                 return NULL;
7647         for (w = r = identifier; *r != 0; r++)
7648         {
7649                 char c = *r;
7650                 if (c == '\\') {
7651                         r++;
7652                         if (*r == 0)
7653                                 break;
7654                         c = *r;
7655                 }
7656                 *w = c;
7657                 w++;
7658         }
7659         if (w != r)
7660                 *w = 0;
7661         return identifier;
7662 }
7663
7664 void
7665 mono_identifier_unescape_info (MonoTypeNameParse* info);
7666
7667 static void
7668 unescape_each_type_argument(void* data, void* user_data)
7669 {
7670         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
7671         mono_identifier_unescape_info (info);
7672 }
7673
7674 static void
7675 unescape_each_nested_name (void* data, void* user_data)
7676 {
7677         char* nested_name = (char*) data;
7678         mono_identifier_unescape_type_name_chars(nested_name);
7679 }
7680
7681 /**
7682  * mono_identifier_unescape_info:
7683  *
7684  * @info: a parsed display form of an (optionally assembly qualified) full type name.
7685  *
7686  * Returns: nothing.
7687  *
7688  * Destructively updates the info by unescaping the identifiers that
7689  * comprise the type namespace, name, nested types (if any) and
7690  * generic type arguments (if any).
7691  *
7692  * The resulting info has the names in internal form.
7693  *
7694  */
7695 void
7696 mono_identifier_unescape_info (MonoTypeNameParse *info)
7697 {
7698         if (!info)
7699                 return;
7700         mono_identifier_unescape_type_name_chars(info->name_space);
7701         mono_identifier_unescape_type_name_chars(info->name);
7702         // but don't escape info->assembly
7703         if (info->type_arguments)
7704                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
7705         if (info->nested)
7706                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
7707 }
7708
7709 int
7710 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7711 {
7712         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
7713         if (ok) {
7714                 mono_identifier_unescape_info (info);
7715         }
7716         return ok;
7717 }
7718
7719 static MonoType*
7720 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7721 {
7722         gboolean type_resolve = FALSE;
7723         MonoType *type;
7724         MonoImage *rootimage = image;
7725
7726         if (info->assembly.name) {
7727                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7728                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7729                         /* 
7730                          * This could happen in the AOT compiler case when the search hook is not
7731                          * installed.
7732                          */
7733                         assembly = image->assembly;
7734                 if (!assembly) {
7735                         /* then we must load the assembly ourselve - see #60439 */
7736                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7737                         if (!assembly)
7738                                 return NULL;
7739                 }
7740                 image = assembly->image;
7741         } else if (!image) {
7742                 image = mono_defaults.corlib;
7743         }
7744
7745         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7746         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7747                 image = mono_defaults.corlib;
7748                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7749         }
7750
7751         return type;
7752 }
7753
7754 static MonoType*
7755 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7756 {
7757         MonoClass *klass;
7758         GList *mod;
7759         int modval;
7760         gboolean bounded = FALSE;
7761         
7762         if (!image)
7763                 image = mono_defaults.corlib;
7764
7765         if (!rootimage)
7766                 rootimage = mono_defaults.corlib;
7767
7768         if (ignorecase) {
7769                 MonoError error;
7770                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7771                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7772         } else {
7773                 klass = mono_class_from_name (image, info->name_space, info->name);
7774         }
7775         if (!klass)
7776                 return NULL;
7777         for (mod = info->nested; mod; mod = mod->next) {
7778                 gpointer iter = NULL;
7779                 MonoClass *parent;
7780
7781                 parent = klass;
7782                 mono_class_init (parent);
7783
7784                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7785                         char *lastp;
7786                         char *nested_name, *nested_nspace;
7787                         gboolean match = TRUE;
7788
7789                         lastp = strrchr (mod->data, '.');
7790                         if (lastp) {
7791                                 /* Nested classes can have namespaces */
7792                                 int nspace_len;
7793
7794                                 nested_name = g_strdup (lastp + 1);
7795                                 nspace_len = lastp - (char*)mod->data;
7796                                 nested_nspace = g_malloc (nspace_len + 1);
7797                                 memcpy (nested_nspace, mod->data, nspace_len);
7798                                 nested_nspace [nspace_len] = '\0';
7799
7800                         } else {
7801                                 nested_name = mod->data;
7802                                 nested_nspace = NULL;
7803                         }
7804
7805                         if (nested_nspace) {
7806                                 if (ignorecase) {
7807                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7808                                                 match = FALSE;
7809                                 } else {
7810                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7811                                                 match = FALSE;
7812                                 }
7813                         }
7814                         if (match) {
7815                                 if (ignorecase) {
7816                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7817                                                 match = FALSE;
7818                                 } else {
7819                                         if (strcmp (klass->name, nested_name) != 0)
7820                                                 match = FALSE;
7821                                 }
7822                         }
7823                         if (lastp) {
7824                                 g_free (nested_name);
7825                                 g_free (nested_nspace);
7826                         }
7827                         if (match)
7828                                 break;
7829                 }
7830
7831                 if (!klass)
7832                         break;
7833         }
7834         if (!klass)
7835                 return NULL;
7836
7837         if (info->type_arguments) {
7838                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7839                 MonoReflectionType *the_type;
7840                 MonoType *instance;
7841                 int i;
7842
7843                 for (i = 0; i < info->type_arguments->len; i++) {
7844                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7845
7846                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7847                         if (!type_args [i]) {
7848                                 g_free (type_args);
7849                                 return NULL;
7850                         }
7851                 }
7852
7853                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7854
7855                 instance = mono_reflection_bind_generic_parameters (
7856                         the_type, info->type_arguments->len, type_args);
7857
7858                 g_free (type_args);
7859                 if (!instance)
7860                         return NULL;
7861
7862                 klass = mono_class_from_mono_type (instance);
7863         }
7864
7865         for (mod = info->modifiers; mod; mod = mod->next) {
7866                 modval = GPOINTER_TO_UINT (mod->data);
7867                 if (!modval) { /* byref: must be last modifier */
7868                         return &klass->this_arg;
7869                 } else if (modval == -1) {
7870                         klass = mono_ptr_class_get (&klass->byval_arg);
7871                 } else if (modval == -2) {
7872                         bounded = TRUE;
7873                 } else { /* array rank */
7874                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7875                 }
7876         }
7877
7878         return &klass->byval_arg;
7879 }
7880
7881 /*
7882  * mono_reflection_get_type:
7883  * @image: a metadata context
7884  * @info: type description structure
7885  * @ignorecase: flag for case-insensitive string compares
7886  * @type_resolve: whenever type resolve was already tried
7887  *
7888  * Build a MonoType from the type description in @info.
7889  * 
7890  */
7891
7892 MonoType*
7893 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7894         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7895 }
7896
7897 static MonoType*
7898 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7899 {
7900         MonoReflectionAssemblyBuilder *abuilder;
7901         MonoType *type;
7902         int i;
7903
7904         g_assert (assembly_is_dynamic (assembly));
7905         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7906
7907         /* Enumerate all modules */
7908
7909         type = NULL;
7910         if (abuilder->modules) {
7911                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7912                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7913                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7914                         if (type)
7915                                 break;
7916                 }
7917         }
7918
7919         if (!type && abuilder->loaded_modules) {
7920                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7921                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7922                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7923                         if (type)
7924                                 break;
7925                 }
7926         }
7927
7928         return type;
7929 }
7930         
7931 MonoType*
7932 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7933 {
7934         MonoType *type;
7935         MonoReflectionAssembly *assembly;
7936         GString *fullName;
7937         GList *mod;
7938
7939         if (image && image_is_dynamic (image))
7940                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7941         else
7942                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7943         if (type)
7944                 return type;
7945         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7946                 return NULL;
7947
7948         if (type_resolve) {
7949                 if (*type_resolve) 
7950                         return NULL;
7951                 else
7952                         *type_resolve = TRUE;
7953         }
7954         
7955         /* Reconstruct the type name */
7956         fullName = g_string_new ("");
7957         if (info->name_space && (info->name_space [0] != '\0'))
7958                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7959         else
7960                 g_string_printf (fullName, "%s", info->name);
7961         for (mod = info->nested; mod; mod = mod->next)
7962                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7963
7964         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7965         if (assembly) {
7966                 if (assembly_is_dynamic (assembly->assembly))
7967                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7968                 else
7969                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7970                                                                                                           info, ignorecase);
7971         }
7972         g_string_free (fullName, TRUE);
7973         return type;
7974 }
7975
7976 void
7977 mono_reflection_free_type_info (MonoTypeNameParse *info)
7978 {
7979         g_list_free (info->modifiers);
7980         g_list_free (info->nested);
7981
7982         if (info->type_arguments) {
7983                 int i;
7984
7985                 for (i = 0; i < info->type_arguments->len; i++) {
7986                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7987
7988                         mono_reflection_free_type_info (subinfo);
7989                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7990                         g_free (subinfo);
7991                 }
7992
7993                 g_ptr_array_free (info->type_arguments, TRUE);
7994         }
7995 }
7996
7997 /*
7998  * mono_reflection_type_from_name:
7999  * @name: type name.
8000  * @image: a metadata context (can be NULL).
8001  *
8002  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8003  * it defaults to get the type from @image or, if @image is NULL or loading
8004  * from it fails, uses corlib.
8005  * 
8006  */
8007 MonoType*
8008 mono_reflection_type_from_name (char *name, MonoImage *image)
8009 {
8010         MonoType *type = NULL;
8011         MonoTypeNameParse info;
8012         char *tmp;
8013
8014         /* Make a copy since parse_type modifies its argument */
8015         tmp = g_strdup (name);
8016         
8017         /*g_print ("requested type %s\n", str);*/
8018         if (mono_reflection_parse_type (tmp, &info)) {
8019                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8020         }
8021
8022         g_free (tmp);
8023         mono_reflection_free_type_info (&info);
8024         return type;
8025 }
8026
8027 /*
8028  * mono_reflection_get_token:
8029  *
8030  *   Return the metadata token of OBJ which should be an object
8031  * representing a metadata element.
8032  */
8033 guint32
8034 mono_reflection_get_token (MonoObject *obj)
8035 {
8036         MonoClass *klass;
8037         guint32 token = 0;
8038
8039         klass = obj->vtable->klass;
8040
8041         if (strcmp (klass->name, "MethodBuilder") == 0) {
8042                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8043
8044                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8045         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8046                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8047
8048                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8049         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8050                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8051
8052                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8053         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8054                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8055                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8056         } else if (strcmp (klass->name, "MonoType") == 0) {
8057                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8058                 MonoClass *mc = mono_class_from_mono_type (type);
8059                 if (!mono_class_init (mc))
8060                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8061
8062                 token = mc->type_token;
8063         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8064                    strcmp (klass->name, "MonoMethod") == 0 ||
8065                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8066                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8067                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8068                 if (m->method->is_inflated) {
8069                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8070                         return inflated->declaring->token;
8071                 } else {
8072                         token = m->method->token;
8073                 }
8074         } else if (strcmp (klass->name, "MonoField") == 0) {
8075                 MonoReflectionField *f = (MonoReflectionField*)obj;
8076
8077                 if (is_field_on_inst (f->field)) {
8078                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8079
8080                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8081                                 int field_index = f->field - dgclass->fields;
8082                                 MonoObject *obj;
8083
8084                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8085                                 obj = dgclass->field_objects [field_index];
8086                                 return mono_reflection_get_token (obj);
8087                         }
8088                 }
8089                 token = mono_class_get_field_token (f->field);
8090         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8091                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8092
8093                 token = mono_class_get_property_token (p->property);
8094         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8095                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8096
8097                 token = mono_class_get_event_token (p->event);
8098         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8099                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8100                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8101                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8102
8103                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8104         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8105                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8106
8107                 token = m->token;
8108         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8109                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8110         } else {
8111                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8112                 MonoException *ex = mono_get_exception_not_implemented (msg);
8113                 g_free (msg);
8114                 mono_raise_exception (ex);
8115         }
8116
8117         return token;
8118 }
8119
8120 static MonoClass*
8121 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8122 {
8123         char *n;
8124         MonoType *t;
8125         int slen = mono_metadata_decode_value (p, &p);
8126
8127         mono_error_init (error);
8128
8129         n = g_memdup (p, slen + 1);
8130         n [slen] = 0;
8131         t = mono_reflection_type_from_name (n, image);
8132         if (!t) {
8133                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8134                 /* We don't free n, it's consumed by mono_error */
8135                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8136                 return NULL;
8137         }
8138         g_free (n);
8139         p += slen;
8140         *end = p;
8141         return mono_class_from_mono_type (t);
8142 }
8143
8144 static void*
8145 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8146 {
8147         int slen, type = t->type;
8148         MonoClass *tklass = t->data.klass;
8149
8150         mono_error_init (error);
8151
8152 handle_enum:
8153         switch (type) {
8154         case MONO_TYPE_U1:
8155         case MONO_TYPE_I1:
8156         case MONO_TYPE_BOOLEAN: {
8157                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8158                 *bval = *p;
8159                 *end = p + 1;
8160                 return bval;
8161         }
8162         case MONO_TYPE_CHAR:
8163         case MONO_TYPE_U2:
8164         case MONO_TYPE_I2: {
8165                 guint16 *val = g_malloc (sizeof (guint16));
8166                 *val = read16 (p);
8167                 *end = p + 2;
8168                 return val;
8169         }
8170 #if SIZEOF_VOID_P == 4
8171         case MONO_TYPE_U:
8172         case MONO_TYPE_I:
8173 #endif
8174         case MONO_TYPE_R4:
8175         case MONO_TYPE_U4:
8176         case MONO_TYPE_I4: {
8177                 guint32 *val = g_malloc (sizeof (guint32));
8178                 *val = read32 (p);
8179                 *end = p + 4;
8180                 return val;
8181         }
8182 #if SIZEOF_VOID_P == 8
8183         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8184         case MONO_TYPE_I:
8185 #endif
8186         case MONO_TYPE_U8:
8187         case MONO_TYPE_I8: {
8188                 guint64 *val = g_malloc (sizeof (guint64));
8189                 *val = read64 (p);
8190                 *end = p + 8;
8191                 return val;
8192         }
8193         case MONO_TYPE_R8: {
8194                 double *val = g_malloc (sizeof (double));
8195                 readr8 (p, val);
8196                 *end = p + 8;
8197                 return val;
8198         }
8199         case MONO_TYPE_VALUETYPE:
8200                 if (t->data.klass->enumtype) {
8201                         type = mono_class_enum_basetype (t->data.klass)->type;
8202                         goto handle_enum;
8203                 } else {
8204                         MonoClass *k =  t->data.klass;
8205                         
8206                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8207                                 guint64 *val = g_malloc (sizeof (guint64));
8208                                 *val = read64 (p);
8209                                 *end = p + 8;
8210                                 return val;
8211                         }
8212                 }
8213                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8214                 break;
8215                 
8216         case MONO_TYPE_STRING:
8217                 if (*p == (char)0xFF) {
8218                         *end = p + 1;
8219                         return NULL;
8220                 }
8221                 slen = mono_metadata_decode_value (p, &p);
8222                 *end = p + slen;
8223                 return mono_string_new_len (mono_domain_get (), p, slen);
8224         case MONO_TYPE_CLASS: {
8225                 char *n;
8226                 MonoType *t;
8227                 if (*p == (char)0xFF) {
8228                         *end = p + 1;
8229                         return NULL;
8230                 }
8231 handle_type:
8232                 slen = mono_metadata_decode_value (p, &p);
8233                 n = g_memdup (p, slen + 1);
8234                 n [slen] = 0;
8235                 t = mono_reflection_type_from_name (n, image);
8236                 if (!t) {
8237                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8238                         /* We don't free n, it's consumed by mono_error */
8239                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8240                         return NULL;
8241                 }
8242                 g_free (n);
8243                 *end = p + slen;
8244                 return mono_type_get_object (mono_domain_get (), t);
8245         }
8246         case MONO_TYPE_OBJECT: {
8247                 char subt = *p++;
8248                 MonoObject *obj;
8249                 MonoClass *subc = NULL;
8250                 void *val;
8251
8252                 if (subt == 0x50) {
8253                         goto handle_type;
8254                 } else if (subt == 0x0E) {
8255                         type = MONO_TYPE_STRING;
8256                         goto handle_enum;
8257                 } else if (subt == 0x1D) {
8258                         MonoType simple_type = {{0}};
8259                         int etype = *p;
8260                         p ++;
8261
8262                         type = MONO_TYPE_SZARRAY;
8263                         if (etype == 0x50) {
8264                                 tklass = mono_defaults.systemtype_class;
8265                         } else if (etype == 0x55) {
8266                                 tklass = load_cattr_enum_type (image, p, &p, error);
8267                                 if (!mono_error_ok (error))
8268                                         return NULL;
8269                         } else {
8270                                 if (etype == 0x51)
8271                                         /* See Partition II, Appendix B3 */
8272                                         etype = MONO_TYPE_OBJECT;
8273                                 simple_type.type = etype;
8274                                 tklass = mono_class_from_mono_type (&simple_type);
8275                         }
8276                         goto handle_enum;
8277                 } else if (subt == 0x55) {
8278                         char *n;
8279                         MonoType *t;
8280                         slen = mono_metadata_decode_value (p, &p);
8281                         n = g_memdup (p, slen + 1);
8282                         n [slen] = 0;
8283                         t = mono_reflection_type_from_name (n, image);
8284                         if (!t) {
8285                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8286                                 /* We don't free n, it's consumed by mono_error */
8287                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8288                                 return NULL;
8289                         }
8290                         g_free (n);
8291                         p += slen;
8292                         subc = mono_class_from_mono_type (t);
8293                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8294                         MonoType simple_type = {{0}};
8295                         simple_type.type = subt;
8296                         subc = mono_class_from_mono_type (&simple_type);
8297                 } else {
8298                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8299                 }
8300                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8301                 obj = NULL;
8302                 if (mono_error_ok (error)) {
8303                         obj = mono_object_new (mono_domain_get (), subc);
8304                         g_assert (!subc->has_references);
8305                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8306                 }
8307
8308                 g_free (val);
8309                 return obj;
8310         }
8311         case MONO_TYPE_SZARRAY: {
8312                 MonoArray *arr;
8313                 guint32 i, alen, basetype;
8314                 alen = read32 (p);
8315                 p += 4;
8316                 if (alen == 0xffffffff) {
8317                         *end = p;
8318                         return NULL;
8319                 }
8320                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8321                 basetype = tklass->byval_arg.type;
8322                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8323                         basetype = mono_class_enum_basetype (tklass)->type;
8324                 switch (basetype)
8325                 {
8326                         case MONO_TYPE_U1:
8327                         case MONO_TYPE_I1:
8328                         case MONO_TYPE_BOOLEAN:
8329                                 for (i = 0; i < alen; i++) {
8330                                         MonoBoolean val = *p++;
8331                                         mono_array_set (arr, MonoBoolean, i, val);
8332                                 }
8333                                 break;
8334                         case MONO_TYPE_CHAR:
8335                         case MONO_TYPE_U2:
8336                         case MONO_TYPE_I2:
8337                                 for (i = 0; i < alen; i++) {
8338                                         guint16 val = read16 (p);
8339                                         mono_array_set (arr, guint16, i, val);
8340                                         p += 2;
8341                                 }
8342                                 break;
8343                         case MONO_TYPE_R4:
8344                         case MONO_TYPE_U4:
8345                         case MONO_TYPE_I4:
8346                                 for (i = 0; i < alen; i++) {
8347                                         guint32 val = read32 (p);
8348                                         mono_array_set (arr, guint32, i, val);
8349                                         p += 4;
8350                                 }
8351                                 break;
8352                         case MONO_TYPE_R8:
8353                                 for (i = 0; i < alen; i++) {
8354                                         double val;
8355                                         readr8 (p, &val);
8356                                         mono_array_set (arr, double, i, val);
8357                                         p += 8;
8358                                 }
8359                                 break;
8360                         case MONO_TYPE_U8:
8361                         case MONO_TYPE_I8:
8362                                 for (i = 0; i < alen; i++) {
8363                                         guint64 val = read64 (p);
8364                                         mono_array_set (arr, guint64, i, val);
8365                                         p += 8;
8366                                 }
8367                                 break;
8368                         case MONO_TYPE_CLASS:
8369                         case MONO_TYPE_OBJECT:
8370                         case MONO_TYPE_STRING:
8371                         case MONO_TYPE_SZARRAY:
8372                                 for (i = 0; i < alen; i++) {
8373                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8374                                         if (!mono_error_ok (error))
8375                                                 return NULL;
8376                                         mono_array_setref (arr, i, item);
8377                                 }
8378                                 break;
8379                         default:
8380                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8381                 }
8382                 *end=p;
8383                 return arr;
8384         }
8385         default:
8386                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8387         }
8388         return NULL;
8389 }
8390
8391 static MonoObject*
8392 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8393 {
8394         static MonoClass *klass;
8395         static MonoMethod *ctor;
8396         MonoObject *retval;
8397         void *params [2], *unboxed;
8398
8399         if (!klass)
8400                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8401         if (!ctor)
8402                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8403         
8404         params [0] = mono_type_get_object (mono_domain_get (), t);
8405         params [1] = val;
8406         retval = mono_object_new (mono_domain_get (), klass);
8407         unboxed = mono_object_unbox (retval);
8408         mono_runtime_invoke (ctor, unboxed, params, NULL);
8409
8410         return retval;
8411 }
8412
8413 static MonoObject*
8414 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8415 {
8416         static MonoClass *klass;
8417         static MonoMethod *ctor;
8418         MonoObject *retval;
8419         void *unboxed, *params [2];
8420
8421         if (!klass)
8422                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8423         if (!ctor)
8424                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8425
8426         params [0] = minfo;
8427         params [1] = typedarg;
8428         retval = mono_object_new (mono_domain_get (), klass);
8429         unboxed = mono_object_unbox (retval);
8430         mono_runtime_invoke (ctor, unboxed, params, NULL);
8431
8432         return retval;
8433 }
8434
8435 static gboolean
8436 type_is_reference (MonoType *type)
8437 {
8438         switch (type->type) {
8439         case MONO_TYPE_BOOLEAN:
8440         case MONO_TYPE_CHAR:
8441         case MONO_TYPE_U:
8442         case MONO_TYPE_I:
8443         case MONO_TYPE_U1:
8444         case MONO_TYPE_I1:
8445         case MONO_TYPE_U2:
8446         case MONO_TYPE_I2:
8447         case MONO_TYPE_U4:
8448         case MONO_TYPE_I4:
8449         case MONO_TYPE_U8:
8450         case MONO_TYPE_I8:
8451         case MONO_TYPE_R8:
8452         case MONO_TYPE_R4:
8453         case MONO_TYPE_VALUETYPE:
8454                 return FALSE;
8455         default:
8456                 return TRUE;
8457         }
8458 }
8459
8460 static void
8461 free_param_data (MonoMethodSignature *sig, void **params) {
8462         int i;
8463         for (i = 0; i < sig->param_count; ++i) {
8464                 if (!type_is_reference (sig->params [i]))
8465                         g_free (params [i]);
8466         }
8467 }
8468
8469 /*
8470  * Find the field index in the metadata FieldDef table.
8471  */
8472 static guint32
8473 find_field_index (MonoClass *klass, MonoClassField *field) {
8474         int i;
8475
8476         for (i = 0; i < klass->field.count; ++i) {
8477                 if (field == &klass->fields [i])
8478                         return klass->field.first + 1 + i;
8479         }
8480         return 0;
8481 }
8482
8483 /*
8484  * Find the property index in the metadata Property table.
8485  */
8486 static guint32
8487 find_property_index (MonoClass *klass, MonoProperty *property) {
8488         int i;
8489
8490         for (i = 0; i < klass->ext->property.count; ++i) {
8491                 if (property == &klass->ext->properties [i])
8492                         return klass->ext->property.first + 1 + i;
8493         }
8494         return 0;
8495 }
8496
8497 /*
8498  * Find the event index in the metadata Event table.
8499  */
8500 static guint32
8501 find_event_index (MonoClass *klass, MonoEvent *event) {
8502         int i;
8503
8504         for (i = 0; i < klass->ext->event.count; ++i) {
8505                 if (event == &klass->ext->events [i])
8506                         return klass->ext->event.first + 1 + i;
8507         }
8508         return 0;
8509 }
8510
8511 static MonoObject*
8512 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8513 {
8514         const char *p = (const char*)data;
8515         const char *named;
8516         guint32 i, j, num_named;
8517         MonoObject *attr;
8518         void *params_buf [32];
8519         void **params = NULL;
8520         MonoMethodSignature *sig;
8521         MonoObject *exc = NULL;
8522
8523         mono_error_init (error);
8524
8525         mono_class_init (method->klass);
8526
8527         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8528                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8529                 return NULL;
8530         }
8531
8532         if (len == 0) {
8533                 attr = mono_object_new (mono_domain_get (), method->klass);
8534                 mono_runtime_invoke (method, attr, NULL, NULL);
8535                 return attr;
8536         }
8537
8538         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8539                 return NULL;
8540
8541         /*g_print ("got attr %s\n", method->klass->name);*/
8542
8543         sig = mono_method_signature (method);
8544         if (sig->param_count < 32) {
8545                 params = params_buf;
8546                 memset (params, 0, sizeof (void*) * sig->param_count);
8547         } else {
8548                 /* Allocate using GC so it gets GC tracking */
8549                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8550         }
8551
8552         /* skip prolog */
8553         p += 2;
8554         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8555                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8556                 if (!mono_error_ok (error))
8557                         goto fail;
8558         }
8559
8560         named = p;
8561         attr = mono_object_new (mono_domain_get (), method->klass);
8562
8563         mono_runtime_invoke (method, attr, params, &exc);
8564         if (exc)
8565                 goto fail;
8566         num_named = read16 (named);
8567         named += 2;
8568         for (j = 0; j < num_named; j++) {
8569                 gint name_len;
8570                 char *name, named_type, data_type;
8571                 named_type = *named++;
8572                 data_type = *named++; /* type of data */
8573                 if (data_type == MONO_TYPE_SZARRAY)
8574                         data_type = *named++;
8575                 if (data_type == MONO_TYPE_ENUM) {
8576                         gint type_len;
8577                         char *type_name;
8578                         type_len = mono_metadata_decode_blob_size (named, &named);
8579                         type_name = g_malloc (type_len + 1);
8580                         memcpy (type_name, named, type_len);
8581                         type_name [type_len] = 0;
8582                         named += type_len;
8583                         /* FIXME: lookup the type and check type consistency */
8584                         g_free (type_name);
8585                 }
8586                 name_len = mono_metadata_decode_blob_size (named, &named);
8587                 name = g_malloc (name_len + 1);
8588                 memcpy (name, named, name_len);
8589                 name [name_len] = 0;
8590                 named += name_len;
8591                 if (named_type == 0x53) {
8592                         MonoClassField *field;
8593                         void *val;
8594
8595                         /* how this fail is a blackbox */
8596                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8597                         if (!field) {
8598                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8599                                 g_free (name);
8600                                 goto fail;
8601                         }
8602
8603                         val = load_cattr_value (image, field->type, named, &named, error);
8604                         if (!mono_error_ok (error)) {
8605                                 g_free (name);
8606                                 if (!type_is_reference (field->type))
8607                                         g_free (val);
8608                                 goto fail;
8609                         }
8610
8611                         mono_field_set_value (attr, field, val);
8612                         if (!type_is_reference (field->type))
8613                                 g_free (val);
8614                 } else if (named_type == 0x54) {
8615                         MonoProperty *prop;
8616                         void *pparams [1];
8617                         MonoType *prop_type;
8618
8619                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8620
8621                         if (!prop) {
8622                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8623                                 g_free (name);
8624                                 goto fail;
8625                         }
8626
8627                         if (!prop->set) {
8628                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8629                                 g_free (name);
8630                                 goto fail;
8631                         }
8632
8633                         /* can we have more that 1 arg in a custom attr named property? */
8634                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8635                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8636
8637                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8638                         if (!mono_error_ok (error)) {
8639                                 g_free (name);
8640                                 if (!type_is_reference (prop_type))
8641                                         g_free (pparams [0]);
8642                                 goto fail;
8643                         }
8644
8645
8646                         mono_property_set_value (prop, attr, pparams, NULL);
8647                         if (!type_is_reference (prop_type))
8648                                 g_free (pparams [0]);
8649                 }
8650                 g_free (name);
8651         }
8652
8653         free_param_data (method->signature, params);
8654         if (params != params_buf)
8655                 mono_gc_free_fixed (params);
8656
8657         return attr;
8658
8659 fail:
8660         free_param_data (method->signature, params);
8661         if (params != params_buf)
8662                 mono_gc_free_fixed (params);
8663         if (exc)
8664                 mono_raise_exception ((MonoException*)exc);
8665         return NULL;
8666 }
8667         
8668 /*
8669  * mono_reflection_create_custom_attr_data_args:
8670  *
8671  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8672  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8673  * NAMED_ARG_INFO will contain information about the named arguments.
8674  */
8675 void
8676 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)
8677 {
8678         MonoArray *typedargs, *namedargs;
8679         MonoClass *attrklass;
8680         MonoDomain *domain;
8681         const char *p = (const char*)data;
8682         const char *named;
8683         guint32 i, j, num_named;
8684         CattrNamedArg *arginfo = NULL;
8685
8686         *typed_args = NULL;
8687         *named_args = NULL;
8688         *named_arg_info = NULL;
8689
8690         mono_error_init (error);
8691
8692         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8693                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8694                 return;
8695         }
8696
8697         mono_class_init (method->klass);
8698         
8699         domain = mono_domain_get ();
8700
8701         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8702                 return;
8703
8704         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8705         
8706         /* skip prolog */
8707         p += 2;
8708         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8709                 MonoObject *obj;
8710                 void *val;
8711
8712                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8713                 if (!mono_error_ok (error)) {
8714                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8715                                 g_free (val);
8716                         return;
8717                 }
8718
8719                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8720                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8721                 mono_array_setref (typedargs, i, obj);
8722
8723                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8724                         g_free (val);
8725         }
8726
8727         named = p;
8728         num_named = read16 (named);
8729         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8730         named += 2;
8731         attrklass = method->klass;
8732
8733         arginfo = g_new0 (CattrNamedArg, num_named);
8734         *named_arg_info = arginfo;
8735
8736         for (j = 0; j < num_named; j++) {
8737                 gint name_len;
8738                 char *name, named_type, data_type;
8739                 named_type = *named++;
8740                 data_type = *named++; /* type of data */
8741                 if (data_type == MONO_TYPE_SZARRAY)
8742                         data_type = *named++;
8743                 if (data_type == MONO_TYPE_ENUM) {
8744                         gint type_len;
8745                         char *type_name;
8746                         type_len = mono_metadata_decode_blob_size (named, &named);
8747                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8748                                 goto fail;
8749
8750                         type_name = g_malloc (type_len + 1);
8751                         memcpy (type_name, named, type_len);
8752                         type_name [type_len] = 0;
8753                         named += type_len;
8754                         /* FIXME: lookup the type and check type consistency */
8755                         g_free (type_name);
8756                 }
8757                 name_len = mono_metadata_decode_blob_size (named, &named);
8758                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8759                         goto fail;
8760                 name = g_malloc (name_len + 1);
8761                 memcpy (name, named, name_len);
8762                 name [name_len] = 0;
8763                 named += name_len;
8764                 if (named_type == 0x53) {
8765                         MonoObject *obj;
8766                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8767                         void *val;
8768
8769                         if (!field) {
8770                                 g_free (name);
8771                                 goto fail;
8772                         }
8773
8774                         arginfo [j].type = field->type;
8775                         arginfo [j].field = field;
8776
8777                         val = load_cattr_value (image, field->type, named, &named, error);
8778                         if (!mono_error_ok (error)) {
8779                                 if (!type_is_reference (field->type))
8780                                         g_free (val);
8781                                 g_free (name);
8782                                 return;
8783                         }
8784
8785                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8786                         mono_array_setref (namedargs, j, obj);
8787                         if (!type_is_reference (field->type))
8788                                 g_free (val);
8789                 } else if (named_type == 0x54) {
8790                         MonoObject *obj;
8791                         MonoType *prop_type;
8792                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8793                         void *val;
8794
8795                         if (!prop || !prop->set) {
8796                                 g_free (name);
8797                                 goto fail;
8798                         }
8799
8800                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8801                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8802
8803                         arginfo [j].type = prop_type;
8804                         arginfo [j].prop = prop;
8805
8806                         val = load_cattr_value (image, prop_type, named, &named, error);
8807                         if (!mono_error_ok (error)) {
8808                                 if (!type_is_reference (prop_type))
8809                                         g_free (val);
8810                                 g_free (name);
8811                                 return;
8812                         }
8813
8814                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8815                         mono_array_setref (namedargs, j, obj);
8816                         if (!type_is_reference (prop_type))
8817                                 g_free (val);
8818                 }
8819                 g_free (name);
8820         }
8821
8822         *typed_args = typedargs;
8823         *named_args = namedargs;
8824         return;
8825 fail:
8826         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8827         g_free (arginfo);
8828         *named_arg_info = NULL;
8829 }
8830
8831 void
8832 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8833 {
8834         MonoDomain *domain;
8835         MonoArray *typedargs, *namedargs;
8836         MonoImage *image;
8837         MonoMethod *method;
8838         CattrNamedArg *arginfo = NULL;
8839         MonoError error;
8840         int i;
8841
8842         *ctor_args = NULL;
8843         *named_args = NULL;
8844
8845         if (len == 0)
8846                 return;
8847
8848         image = assembly->assembly->image;
8849         method = ref_method->method;
8850         domain = mono_object_domain (ref_method);
8851
8852         if (!mono_class_init (method->klass))
8853                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8854
8855         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8856         if (!mono_error_ok (&error))
8857                 mono_error_raise_exception (&error);
8858         if (mono_loader_get_last_error ())
8859                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8860
8861         if (!typedargs || !namedargs) {
8862                 g_free (arginfo);
8863                 return;
8864         }
8865
8866         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8867                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8868                 MonoObject *typedarg;
8869
8870                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8871                 mono_array_setref (typedargs, i, typedarg);
8872         }
8873
8874         for (i = 0; i < mono_array_length (namedargs); ++i) {
8875                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8876                 MonoObject *typedarg, *namedarg, *minfo;
8877
8878                 if (arginfo [i].prop)
8879                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8880                 else
8881                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8882
8883                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8884                 namedarg = create_cattr_named_arg (minfo, typedarg);
8885
8886                 mono_array_setref (namedargs, i, namedarg);
8887         }
8888
8889         *ctor_args = typedargs;
8890         *named_args = namedargs;
8891         g_free (arginfo);
8892 }
8893
8894 static MonoObject*
8895 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8896 {
8897         static MonoMethod *ctor;
8898         MonoDomain *domain;
8899         MonoObject *attr;
8900         void *params [4];
8901
8902         g_assert (image->assembly);
8903
8904         if (!ctor)
8905                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8906
8907         domain = mono_domain_get ();
8908         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8909         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8910         params [1] = mono_assembly_get_object (domain, image->assembly);
8911         params [2] = (gpointer)&cattr->data;
8912         params [3] = &cattr->data_size;
8913         mono_runtime_invoke (ctor, attr, params, NULL);
8914         return attr;
8915 }
8916
8917 static MonoArray*
8918 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8919 {
8920         MonoArray *result;
8921         MonoObject *attr;
8922         int i, n;
8923
8924         mono_error_init (error);
8925
8926         n = 0;
8927         for (i = 0; i < cinfo->num_attrs; ++i) {
8928                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8929                         n ++;
8930         }
8931
8932         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8933         n = 0;
8934         for (i = 0; i < cinfo->num_attrs; ++i) {
8935                 if (!cinfo->attrs [i].ctor)
8936                         /* The cattr type is not finished yet */
8937                         /* We should include the type name but cinfo doesn't contain it */
8938                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8939                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8940                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8941                         if (!mono_error_ok (error))
8942                                 return result;
8943                         mono_array_setref (result, n, attr);
8944                         n ++;
8945                 }
8946         }
8947         return result;
8948 }
8949
8950 MonoArray*
8951 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8952 {
8953         MonoError error;
8954         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8955         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8956
8957         return result;
8958 }
8959
8960 static MonoArray*
8961 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8962 {
8963         MonoArray *result;
8964         MonoObject *attr;
8965         int i;
8966         
8967         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8968         for (i = 0; i < cinfo->num_attrs; ++i) {
8969                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8970                 mono_array_setref (result, i, attr);
8971         }
8972         return result;
8973 }
8974
8975 /**
8976  * mono_custom_attrs_from_index:
8977  *
8978  * Returns: NULL if no attributes are found or if a loading error occurs.
8979  */
8980 MonoCustomAttrInfo*
8981 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8982 {
8983         guint32 mtoken, i, len;
8984         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8985         MonoTableInfo *ca;
8986         MonoCustomAttrInfo *ainfo;
8987         GList *tmp, *list = NULL;
8988         const char *data;
8989         MonoCustomAttrEntry* attr;
8990
8991         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8992
8993         i = mono_metadata_custom_attrs_from_index (image, idx);
8994         if (!i)
8995                 return NULL;
8996         i --;
8997         while (i < ca->rows) {
8998                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8999                         break;
9000                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9001                 ++i;
9002         }
9003         len = g_list_length (list);
9004         if (!len)
9005                 return NULL;
9006         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9007         ainfo->num_attrs = len;
9008         ainfo->image = image;
9009         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9010                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9011                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9012                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9013                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9014                         mtoken |= MONO_TOKEN_METHOD_DEF;
9015                         break;
9016                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9017                         mtoken |= MONO_TOKEN_MEMBER_REF;
9018                         break;
9019                 default:
9020                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9021                         break;
9022                 }
9023                 attr = &ainfo->attrs [i - 1];
9024                 attr->ctor = mono_get_method (image, mtoken, NULL);
9025                 if (!attr->ctor) {
9026                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
9027                         g_list_free (list);
9028                         g_free (ainfo);
9029                         return NULL;
9030                 }
9031
9032                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9033                         /*FIXME raising an exception here doesn't make any sense*/
9034                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9035                         g_list_free (list);
9036                         g_free (ainfo);
9037                         return NULL;
9038                 }
9039                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9040                 attr->data_size = mono_metadata_decode_value (data, &data);
9041                 attr->data = (guchar*)data;
9042         }
9043         g_list_free (list);
9044
9045         return ainfo;
9046 }
9047
9048 MonoCustomAttrInfo*
9049 mono_custom_attrs_from_method (MonoMethod *method)
9050 {
9051         guint32 idx;
9052
9053         /*
9054          * An instantiated method has the same cattrs as the generic method definition.
9055          *
9056          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9057          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9058          */
9059         if (method->is_inflated)
9060                 method = ((MonoMethodInflated *) method)->declaring;
9061         
9062         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9063                 return lookup_custom_attr (method->klass->image, method);
9064
9065         if (!method->token)
9066                 /* Synthetic methods */
9067                 return NULL;
9068
9069         idx = mono_method_get_index (method);
9070         idx <<= MONO_CUSTOM_ATTR_BITS;
9071         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9072         return mono_custom_attrs_from_index (method->klass->image, idx);
9073 }
9074
9075 MonoCustomAttrInfo*
9076 mono_custom_attrs_from_class (MonoClass *klass)
9077 {
9078         guint32 idx;
9079
9080         if (klass->generic_class)
9081                 klass = klass->generic_class->container_class;
9082
9083         if (image_is_dynamic (klass->image))
9084                 return lookup_custom_attr (klass->image, klass);
9085
9086         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9087                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9088                 idx <<= MONO_CUSTOM_ATTR_BITS;
9089                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9090         } else {
9091                 idx = mono_metadata_token_index (klass->type_token);
9092                 idx <<= MONO_CUSTOM_ATTR_BITS;
9093                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9094         }
9095         return mono_custom_attrs_from_index (klass->image, idx);
9096 }
9097
9098 MonoCustomAttrInfo*
9099 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9100 {
9101         guint32 idx;
9102         
9103         if (image_is_dynamic (assembly->image))
9104                 return lookup_custom_attr (assembly->image, assembly);
9105         idx = 1; /* there is only one assembly */
9106         idx <<= MONO_CUSTOM_ATTR_BITS;
9107         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9108         return mono_custom_attrs_from_index (assembly->image, idx);
9109 }
9110
9111 static MonoCustomAttrInfo*
9112 mono_custom_attrs_from_module (MonoImage *image)
9113 {
9114         guint32 idx;
9115         
9116         if (image_is_dynamic (image))
9117                 return lookup_custom_attr (image, image);
9118         idx = 1; /* there is only one module */
9119         idx <<= MONO_CUSTOM_ATTR_BITS;
9120         idx |= MONO_CUSTOM_ATTR_MODULE;
9121         return mono_custom_attrs_from_index (image, idx);
9122 }
9123
9124 MonoCustomAttrInfo*
9125 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9126 {
9127         guint32 idx;
9128         
9129         if (image_is_dynamic (klass->image)) {
9130                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9131                 return lookup_custom_attr (klass->image, property);
9132         }
9133         idx = find_property_index (klass, property);
9134         idx <<= MONO_CUSTOM_ATTR_BITS;
9135         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9136         return mono_custom_attrs_from_index (klass->image, idx);
9137 }
9138
9139 MonoCustomAttrInfo*
9140 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9141 {
9142         guint32 idx;
9143         
9144         if (image_is_dynamic (klass->image)) {
9145                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9146                 return lookup_custom_attr (klass->image, event);
9147         }
9148         idx = find_event_index (klass, event);
9149         idx <<= MONO_CUSTOM_ATTR_BITS;
9150         idx |= MONO_CUSTOM_ATTR_EVENT;
9151         return mono_custom_attrs_from_index (klass->image, idx);
9152 }
9153
9154 MonoCustomAttrInfo*
9155 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9156 {
9157         guint32 idx;
9158         if (image_is_dynamic (klass->image)) {
9159                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9160                 return lookup_custom_attr (klass->image, field);
9161         }
9162         idx = find_field_index (klass, field);
9163         idx <<= MONO_CUSTOM_ATTR_BITS;
9164         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9165         return mono_custom_attrs_from_index (klass->image, idx);
9166 }
9167
9168 /**
9169  * mono_custom_attrs_from_param:
9170  * @method: handle to the method that we want to retrieve custom parameter information from
9171  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9172  *
9173  * The result must be released with mono_custom_attrs_free().
9174  *
9175  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9176  */
9177 MonoCustomAttrInfo*
9178 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9179 {
9180         MonoTableInfo *ca;
9181         guint32 i, idx, method_index;
9182         guint32 param_list, param_last, param_pos, found;
9183         MonoImage *image;
9184         MonoReflectionMethodAux *aux;
9185
9186         /*
9187          * An instantiated method has the same cattrs as the generic method definition.
9188          *
9189          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9190          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9191          */
9192         if (method->is_inflated)
9193                 method = ((MonoMethodInflated *) method)->declaring;
9194
9195         if (image_is_dynamic (method->klass->image)) {
9196                 MonoCustomAttrInfo *res, *ainfo;
9197                 int size;
9198
9199                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9200                 if (!aux || !aux->param_cattr)
9201                         return NULL;
9202
9203                 /* Need to copy since it will be freed later */
9204                 ainfo = aux->param_cattr [param];
9205                 if (!ainfo)
9206                         return NULL;
9207                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9208                 res = g_malloc0 (size);
9209                 memcpy (res, ainfo, size);
9210                 return res;
9211         }
9212
9213         image = method->klass->image;
9214         method_index = mono_method_get_index (method);
9215         if (!method_index)
9216                 return NULL;
9217         ca = &image->tables [MONO_TABLE_METHOD];
9218
9219         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9220         if (method_index == ca->rows) {
9221                 ca = &image->tables [MONO_TABLE_PARAM];
9222                 param_last = ca->rows + 1;
9223         } else {
9224                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9225                 ca = &image->tables [MONO_TABLE_PARAM];
9226         }
9227         found = FALSE;
9228         for (i = param_list; i < param_last; ++i) {
9229                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9230                 if (param_pos == param) {
9231                         found = TRUE;
9232                         break;
9233                 }
9234         }
9235         if (!found)
9236                 return NULL;
9237         idx = i;
9238         idx <<= MONO_CUSTOM_ATTR_BITS;
9239         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9240         return mono_custom_attrs_from_index (image, idx);
9241 }
9242
9243 gboolean
9244 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9245 {
9246         int i;
9247         MonoClass *klass;
9248         for (i = 0; i < ainfo->num_attrs; ++i) {
9249                 klass = ainfo->attrs [i].ctor->klass;
9250                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9251                         return TRUE;
9252         }
9253         return FALSE;
9254 }
9255
9256 MonoObject*
9257 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9258 {
9259         MonoError error;
9260         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9261         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9262         return res;
9263 }
9264
9265 MonoObject*
9266 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9267 {
9268         int i, attr_index;
9269         MonoClass *klass;
9270         MonoArray *attrs;
9271
9272         mono_error_init (error);
9273
9274         attr_index = -1;
9275         for (i = 0; i < ainfo->num_attrs; ++i) {
9276                 klass = ainfo->attrs [i].ctor->klass;
9277                 if (mono_class_has_parent (klass, attr_klass)) {
9278                         attr_index = i;
9279                         break;
9280                 }
9281         }
9282         if (attr_index == -1)
9283                 return NULL;
9284
9285         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9286         if (!mono_error_ok (error))
9287                 return NULL;
9288         return mono_array_get (attrs, MonoObject*, attr_index);
9289 }
9290
9291 /*
9292  * mono_reflection_get_custom_attrs_info:
9293  * @obj: a reflection object handle
9294  *
9295  * Return the custom attribute info for attributes defined for the
9296  * reflection handle @obj. The objects.
9297  *
9298  * FIXME this function leaks like a sieve for SRE objects.
9299  */
9300 MonoCustomAttrInfo*
9301 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9302 {
9303         MonoClass *klass;
9304         MonoCustomAttrInfo *cinfo = NULL;
9305         
9306         klass = obj->vtable->klass;
9307         if (klass == mono_defaults.monotype_class) {
9308                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9309                 klass = mono_class_from_mono_type (type);
9310                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9311                 cinfo = mono_custom_attrs_from_class (klass);
9312         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9313                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9314                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9315         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9316                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9317                 cinfo = mono_custom_attrs_from_module (module->image);
9318         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9319                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9320                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9321         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9322                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9323                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9324         } else if (strcmp ("MonoField", klass->name) == 0) {
9325                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9326                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9327         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9328                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9329                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9330         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9331                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9332                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9333         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9334                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9335                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9336                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9337                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9338                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9339                 } else if (is_sr_mono_property (member_class)) {
9340                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9341                         MonoMethod *method;
9342                         if (!(method = prop->property->get))
9343                                 method = prop->property->set;
9344                         g_assert (method);
9345
9346                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9347                 } 
9348 #ifndef DISABLE_REFLECTION_EMIT
9349                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9350                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9351                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9352                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9353                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9354                         MonoMethod *method = NULL;
9355                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9356                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9357                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9358                                 method = ((MonoReflectionMethod *)c->cb)->method;
9359                         else
9360                                 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));
9361
9362                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9363                 } 
9364 #endif
9365                 else {
9366                         char *type_name = mono_type_get_full_name (member_class);
9367                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9368                         MonoException *ex = mono_get_exception_not_supported  (msg);
9369                         g_free (type_name);
9370                         g_free (msg);
9371                         mono_raise_exception (ex);
9372                 }
9373         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9374                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9375                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9376         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9377                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9378                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9379         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9380                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9381                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9382         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9383                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9384                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9385         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9386                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9387                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9388         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9389                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9390                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9391         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9392                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9393                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9394         } else { /* handle other types here... */
9395                 g_error ("get custom attrs not yet supported for %s", klass->name);
9396         }
9397
9398         return cinfo;
9399 }
9400
9401 /*
9402  * mono_reflection_get_custom_attrs_by_type:
9403  * @obj: a reflection object handle
9404  *
9405  * Return an array with all the custom attributes defined of the
9406  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9407  * of that type are returned. The objects are fully build. Return NULL if a loading error
9408  * occurs.
9409  */
9410 MonoArray*
9411 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9412 {
9413         MonoArray *result;
9414         MonoCustomAttrInfo *cinfo;
9415
9416         mono_error_init (error);
9417
9418         cinfo = mono_reflection_get_custom_attrs_info (obj);
9419         if (cinfo) {
9420                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9421                 if (!cinfo->cached)
9422                         mono_custom_attrs_free (cinfo);
9423         } else {
9424                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9425                 if (mono_loader_get_last_error ())
9426                         return NULL;
9427                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9428         }
9429
9430         return result;
9431 }
9432
9433 /*
9434  * mono_reflection_get_custom_attrs:
9435  * @obj: a reflection object handle
9436  *
9437  * Return an array with all the custom attributes defined of the
9438  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9439  * occurs.
9440  */
9441 MonoArray*
9442 mono_reflection_get_custom_attrs (MonoObject *obj)
9443 {
9444         MonoError error;
9445
9446         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9447 }
9448
9449 /*
9450  * mono_reflection_get_custom_attrs_data:
9451  * @obj: a reflection obj handle
9452  *
9453  * Returns an array of System.Reflection.CustomAttributeData,
9454  * which include information about attributes reflected on
9455  * types loaded using the Reflection Only methods
9456  */
9457 MonoArray*
9458 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9459 {
9460         MonoArray *result;
9461         MonoCustomAttrInfo *cinfo;
9462
9463         cinfo = mono_reflection_get_custom_attrs_info (obj);
9464         if (cinfo) {
9465                 result = mono_custom_attrs_data_construct (cinfo);
9466                 if (!cinfo->cached)
9467                         mono_custom_attrs_free (cinfo);
9468         } else
9469                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9470
9471         return result;
9472 }
9473
9474 static MonoReflectionType*
9475 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9476 {
9477         static MonoMethod *method_get_underlying_system_type = NULL;
9478         MonoMethod *usertype_method;
9479
9480         if (!method_get_underlying_system_type)
9481                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9482         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9483         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9484 }
9485
9486
9487 static gboolean
9488 is_corlib_type (MonoClass *klass)
9489 {
9490         return klass->image == mono_defaults.corlib;
9491 }
9492
9493 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9494         static MonoClass *cached_class; \
9495         if (cached_class) \
9496                 return cached_class == _class; \
9497         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9498                 cached_class = _class; \
9499                 return TRUE; \
9500         } \
9501         return FALSE; \
9502 } while (0) \
9503
9504
9505 #ifndef DISABLE_REFLECTION_EMIT
9506 static gboolean
9507 is_sre_array (MonoClass *klass)
9508 {
9509         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
9510 }
9511
9512 static gboolean
9513 is_sre_byref (MonoClass *klass)
9514 {
9515         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
9516 }
9517
9518 static gboolean
9519 is_sre_pointer (MonoClass *klass)
9520 {
9521         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
9522 }
9523
9524 static gboolean
9525 is_sre_generic_instance (MonoClass *klass)
9526 {
9527         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
9528 }
9529
9530 static gboolean
9531 is_sre_type_builder (MonoClass *klass)
9532 {
9533         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
9534 }
9535
9536 static gboolean
9537 is_sre_method_builder (MonoClass *klass)
9538 {
9539         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
9540 }
9541
9542 static gboolean
9543 is_sre_ctor_builder (MonoClass *klass)
9544 {
9545         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
9546 }
9547
9548 static gboolean
9549 is_sre_field_builder (MonoClass *klass)
9550 {
9551         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
9552 }
9553
9554 static gboolean
9555 is_sre_method_on_tb_inst (MonoClass *klass)
9556 {
9557         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9558 }
9559
9560 static gboolean
9561 is_sre_ctor_on_tb_inst (MonoClass *klass)
9562 {
9563         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9564 }
9565
9566 MonoType*
9567 mono_reflection_type_get_handle (MonoReflectionType* ref)
9568 {
9569         MonoClass *klass;
9570         if (!ref)
9571                 return NULL;
9572         if (ref->type)
9573                 return ref->type;
9574
9575         if (is_usertype (ref)) {
9576                 ref = mono_reflection_type_get_underlying_system_type (ref);
9577                 if (ref == NULL || is_usertype (ref))
9578                         return NULL;
9579                 if (ref->type)
9580                         return ref->type;
9581         }
9582
9583         klass = mono_object_class (ref);
9584
9585         if (is_sre_array (klass)) {
9586                 MonoType *res;
9587                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9588                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9589                 g_assert (base);
9590                 if (sre_array->rank == 0) //single dimentional array
9591                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9592                 else
9593                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9594                 sre_array->type.type = res;
9595                 return res;
9596         } else if (is_sre_byref (klass)) {
9597                 MonoType *res;
9598                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9599                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9600                 g_assert (base);
9601                 res = &mono_class_from_mono_type (base)->this_arg;
9602                 sre_byref->type.type = res;
9603                 return res;
9604         } else if (is_sre_pointer (klass)) {
9605                 MonoType *res;
9606                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9607                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9608                 g_assert (base);
9609                 res = &mono_ptr_class_get (base)->byval_arg;
9610                 sre_pointer->type.type = res;
9611                 return res;
9612         } else if (is_sre_generic_instance (klass)) {
9613                 MonoType *res, **types;
9614                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9615                 int i, count;
9616
9617                 count = mono_array_length (gclass->type_arguments);
9618                 types = g_new0 (MonoType*, count);
9619                 for (i = 0; i < count; ++i) {
9620                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9621                         types [i] = mono_reflection_type_get_handle (t);
9622                         if (!types[i]) {
9623                                 g_free (types);
9624                                 return NULL;
9625                         }
9626                 }
9627
9628                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9629                 g_free (types);
9630                 g_assert (res);
9631                 gclass->type.type = res;
9632                 return res;
9633         }
9634
9635         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9636         return NULL;
9637 }
9638
9639
9640
9641 void
9642 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9643 {
9644         mono_reflection_type_get_handle (type);
9645 }
9646
9647 void
9648 mono_reflection_register_with_runtime (MonoReflectionType *type)
9649 {
9650         MonoType *res = mono_reflection_type_get_handle (type);
9651         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9652         MonoClass *klass;
9653
9654         if (!res)
9655                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9656
9657         klass = mono_class_from_mono_type (res);
9658
9659         mono_loader_lock (); /*same locking as mono_type_get_object*/
9660         mono_domain_lock (domain);
9661
9662         if (!image_is_dynamic (klass->image)) {
9663                 mono_class_setup_supertypes (klass);
9664         } else {
9665                 if (!domain->type_hash)
9666                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9667                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9668                 mono_g_hash_table_insert (domain->type_hash, res, type);
9669         }
9670         mono_domain_unlock (domain);
9671         mono_loader_unlock ();
9672 }
9673
9674 /**
9675  * LOCKING: Assumes the loader lock is held.
9676  */
9677 static MonoMethodSignature*
9678 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9679         MonoMethodSignature *sig;
9680         int count, i;
9681
9682         count = parameters? mono_array_length (parameters): 0;
9683
9684         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9685         sig->param_count = count;
9686         sig->sentinelpos = -1; /* FIXME */
9687         for (i = 0; i < count; ++i)
9688                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9689         return sig;
9690 }
9691
9692 /**
9693  * LOCKING: Assumes the loader lock is held.
9694  */
9695 static MonoMethodSignature*
9696 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9697         MonoMethodSignature *sig;
9698
9699         sig = parameters_to_signature (image, ctor->parameters);
9700         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9701         sig->ret = &mono_defaults.void_class->byval_arg;
9702         return sig;
9703 }
9704
9705 /**
9706  * LOCKING: Assumes the loader lock is held.
9707  */
9708 static MonoMethodSignature*
9709 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9710         MonoMethodSignature *sig;
9711
9712         sig = parameters_to_signature (image, method->parameters);
9713         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9714         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9715         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9716         return sig;
9717 }
9718
9719 static MonoMethodSignature*
9720 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9721         MonoMethodSignature *sig;
9722
9723         sig = parameters_to_signature (NULL, method->parameters);
9724         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9725         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9726         sig->generic_param_count = 0;
9727         return sig;
9728 }
9729
9730 static void
9731 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9732 {
9733         MonoClass *klass = mono_object_class (prop);
9734         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9735                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9736                 *name = mono_string_to_utf8 (pb->name);
9737                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9738         } else {
9739                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9740                 *name = g_strdup (p->property->name);
9741                 if (p->property->get)
9742                         *type = mono_method_signature (p->property->get)->ret;
9743                 else
9744                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9745         }
9746 }
9747
9748 static void
9749 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9750 {
9751         MonoClass *klass = mono_object_class (field);
9752         if (strcmp (klass->name, "FieldBuilder") == 0) {
9753                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9754                 *name = mono_string_to_utf8 (fb->name);
9755                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9756         } else {
9757                 MonoReflectionField *f = (MonoReflectionField *)field;
9758                 *name = g_strdup (mono_field_get_name (f->field));
9759                 *type = f->field->type;
9760         }
9761 }
9762
9763 #else /* DISABLE_REFLECTION_EMIT */
9764
9765 void
9766 mono_reflection_register_with_runtime (MonoReflectionType *type)
9767 {
9768         /* This is empty */
9769 }
9770
9771 static gboolean
9772 is_sre_type_builder (MonoClass *klass)
9773 {
9774         return FALSE;
9775 }
9776
9777 static gboolean
9778 is_sre_generic_instance (MonoClass *klass)
9779 {
9780         return FALSE;
9781 }
9782
9783 static void
9784 init_type_builder_generics (MonoObject *type)
9785 {
9786 }
9787
9788 #endif /* !DISABLE_REFLECTION_EMIT */
9789
9790
9791 static gboolean
9792 is_sr_mono_field (MonoClass *klass)
9793 {
9794         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
9795 }
9796
9797 static gboolean
9798 is_sr_mono_property (MonoClass *klass)
9799 {
9800         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
9801 }
9802
9803 static gboolean
9804 is_sr_mono_method (MonoClass *klass)
9805 {
9806         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
9807 }
9808
9809 static gboolean
9810 is_sr_mono_cmethod (MonoClass *klass)
9811 {
9812         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
9813 }
9814
9815 static gboolean
9816 is_sr_mono_generic_method (MonoClass *klass)
9817 {
9818         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
9819 }
9820
9821 static gboolean
9822 is_sr_mono_generic_cmethod (MonoClass *klass)
9823 {
9824         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
9825 }
9826
9827 gboolean
9828 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
9829 {
9830         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
9831 }
9832
9833 static gboolean
9834 is_usertype (MonoReflectionType *ref)
9835 {
9836         MonoClass *klass = mono_object_class (ref);
9837         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
9838 }
9839
9840 static MonoReflectionType*
9841 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9842 {
9843         if (!type || type->type)
9844                 return type;
9845
9846         if (is_usertype (type)) {
9847                 type = mono_reflection_type_get_underlying_system_type (type);
9848                 if (is_usertype (type))
9849                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9850         }
9851
9852         return type;
9853 }
9854 /*
9855  * Encode a value in a custom attribute stream of bytes.
9856  * The value to encode is either supplied as an object in argument val
9857  * (valuetypes are boxed), or as a pointer to the data in the
9858  * argument argval.
9859  * @type represents the type of the value
9860  * @buffer is the start of the buffer
9861  * @p the current position in the buffer
9862  * @buflen contains the size of the buffer and is used to return the new buffer size
9863  * if this needs to be realloced.
9864  * @retbuffer and @retp return the start and the position of the buffer
9865  */
9866 static void
9867 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9868 {
9869         MonoTypeEnum simple_type;
9870         
9871         if ((p-buffer) + 10 >= *buflen) {
9872                 char *newbuf;
9873                 *buflen *= 2;
9874                 newbuf = g_realloc (buffer, *buflen);
9875                 p = newbuf + (p-buffer);
9876                 buffer = newbuf;
9877         }
9878         if (!argval)
9879                 argval = ((char*)arg + sizeof (MonoObject));
9880         simple_type = type->type;
9881 handle_enum:
9882         switch (simple_type) {
9883         case MONO_TYPE_BOOLEAN:
9884         case MONO_TYPE_U1:
9885         case MONO_TYPE_I1:
9886                 *p++ = *argval;
9887                 break;
9888         case MONO_TYPE_CHAR:
9889         case MONO_TYPE_U2:
9890         case MONO_TYPE_I2:
9891                 swap_with_size (p, argval, 2, 1);
9892                 p += 2;
9893                 break;
9894         case MONO_TYPE_U4:
9895         case MONO_TYPE_I4:
9896         case MONO_TYPE_R4:
9897                 swap_with_size (p, argval, 4, 1);
9898                 p += 4;
9899                 break;
9900         case MONO_TYPE_R8:
9901                 swap_with_size (p, argval, 8, 1);
9902                 p += 8;
9903                 break;
9904         case MONO_TYPE_U8:
9905         case MONO_TYPE_I8:
9906                 swap_with_size (p, argval, 8, 1);
9907                 p += 8;
9908                 break;
9909         case MONO_TYPE_VALUETYPE:
9910                 if (type->data.klass->enumtype) {
9911                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9912                         goto handle_enum;
9913                 } else {
9914                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9915                 }
9916                 break;
9917         case MONO_TYPE_STRING: {
9918                 char *str;
9919                 guint32 slen;
9920                 if (!arg) {
9921                         *p++ = 0xFF;
9922                         break;
9923                 }
9924                 str = mono_string_to_utf8 ((MonoString*)arg);
9925                 slen = strlen (str);
9926                 if ((p-buffer) + 10 + slen >= *buflen) {
9927                         char *newbuf;
9928                         *buflen *= 2;
9929                         *buflen += slen;
9930                         newbuf = g_realloc (buffer, *buflen);
9931                         p = newbuf + (p-buffer);
9932                         buffer = newbuf;
9933                 }
9934                 mono_metadata_encode_value (slen, p, &p);
9935                 memcpy (p, str, slen);
9936                 p += slen;
9937                 g_free (str);
9938                 break;
9939         }
9940         case MONO_TYPE_CLASS: {
9941                 char *str;
9942                 guint32 slen;
9943                 if (!arg) {
9944                         *p++ = 0xFF;
9945                         break;
9946                 }
9947 handle_type:
9948                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9949                 slen = strlen (str);
9950                 if ((p-buffer) + 10 + slen >= *buflen) {
9951                         char *newbuf;
9952                         *buflen *= 2;
9953                         *buflen += slen;
9954                         newbuf = g_realloc (buffer, *buflen);
9955                         p = newbuf + (p-buffer);
9956                         buffer = newbuf;
9957                 }
9958                 mono_metadata_encode_value (slen, p, &p);
9959                 memcpy (p, str, slen);
9960                 p += slen;
9961                 g_free (str);
9962                 break;
9963         }
9964         case MONO_TYPE_SZARRAY: {
9965                 int len, i;
9966                 MonoClass *eclass, *arg_eclass;
9967
9968                 if (!arg) {
9969                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9970                         break;
9971                 }
9972                 len = mono_array_length ((MonoArray*)arg);
9973                 *p++ = len & 0xff;
9974                 *p++ = (len >> 8) & 0xff;
9975                 *p++ = (len >> 16) & 0xff;
9976                 *p++ = (len >> 24) & 0xff;
9977                 *retp = p;
9978                 *retbuffer = buffer;
9979                 eclass = type->data.klass;
9980                 arg_eclass = mono_object_class (arg)->element_class;
9981
9982                 if (!eclass) {
9983                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9984                         eclass = mono_defaults.object_class;
9985                 }
9986                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9987                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9988                         int elsize = mono_class_array_element_size (arg_eclass);
9989                         for (i = 0; i < len; ++i) {
9990                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9991                                 elptr += elsize;
9992                         }
9993                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9994                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9995                         int elsize = mono_class_array_element_size (eclass);
9996                         for (i = 0; i < len; ++i) {
9997                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9998                                 elptr += elsize;
9999                         }
10000                 } else {
10001                         for (i = 0; i < len; ++i) {
10002                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10003                         }
10004                 }
10005                 break;
10006         }
10007         case MONO_TYPE_OBJECT: {
10008                 MonoClass *klass;
10009                 char *str;
10010                 guint32 slen;
10011
10012                 /*
10013                  * The parameter type is 'object' but the type of the actual
10014                  * argument is not. So we have to add type information to the blob
10015                  * too. This is completely undocumented in the spec.
10016                  */
10017
10018                 if (arg == NULL) {
10019                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10020                         *p++ = 0xFF;
10021                         break;
10022                 }
10023                 
10024                 klass = mono_object_class (arg);
10025
10026                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10027                         *p++ = 0x50;
10028                         goto handle_type;
10029                 } else if (klass->enumtype) {
10030                         *p++ = 0x55;
10031                 } else if (klass == mono_defaults.string_class) {
10032                         simple_type = MONO_TYPE_STRING;
10033                         *p++ = 0x0E;
10034                         goto handle_enum;
10035                 } else if (klass->rank == 1) {
10036                         *p++ = 0x1D;
10037                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10038                                 /* See Partition II, Appendix B3 */
10039                                 *p++ = 0x51;
10040                         else
10041                                 *p++ = klass->element_class->byval_arg.type;
10042                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10043                         break;
10044                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10045                         *p++ = simple_type = klass->byval_arg.type;
10046                         goto handle_enum;
10047                 } else {
10048                         g_error ("unhandled type in custom attr");
10049                 }
10050                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10051                 slen = strlen (str);
10052                 if ((p-buffer) + 10 + slen >= *buflen) {
10053                         char *newbuf;
10054                         *buflen *= 2;
10055                         *buflen += slen;
10056                         newbuf = g_realloc (buffer, *buflen);
10057                         p = newbuf + (p-buffer);
10058                         buffer = newbuf;
10059                 }
10060                 mono_metadata_encode_value (slen, p, &p);
10061                 memcpy (p, str, slen);
10062                 p += slen;
10063                 g_free (str);
10064                 simple_type = mono_class_enum_basetype (klass)->type;
10065                 goto handle_enum;
10066         }
10067         default:
10068                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10069         }
10070         *retp = p;
10071         *retbuffer = buffer;
10072 }
10073
10074 static void
10075 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10076 {
10077         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10078                 char *str = type_get_qualified_name (type, NULL);
10079                 int slen = strlen (str);
10080
10081                 *p++ = 0x55;
10082                 /*
10083                  * This seems to be optional...
10084                  * *p++ = 0x80;
10085                  */
10086                 mono_metadata_encode_value (slen, p, &p);
10087                 memcpy (p, str, slen);
10088                 p += slen;
10089                 g_free (str);
10090         } else if (type->type == MONO_TYPE_OBJECT) {
10091                 *p++ = 0x51;
10092         } else if (type->type == MONO_TYPE_CLASS) {
10093                 /* it should be a type: encode_cattr_value () has the check */
10094                 *p++ = 0x50;
10095         } else {
10096                 mono_metadata_encode_value (type->type, p, &p);
10097                 if (type->type == MONO_TYPE_SZARRAY)
10098                         /* See the examples in Partition VI, Annex B */
10099                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10100         }
10101
10102         *retp = p;
10103 }
10104
10105 #ifndef DISABLE_REFLECTION_EMIT
10106 static void
10107 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10108 {
10109         int len;
10110         /* Preallocate a large enough buffer */
10111         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10112                 char *str = type_get_qualified_name (type, NULL);
10113                 len = strlen (str);
10114                 g_free (str);
10115         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10116                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10117                 len = strlen (str);
10118                 g_free (str);
10119         } else {
10120                 len = 0;
10121         }
10122         len += strlen (name);
10123
10124         if ((p-buffer) + 20 + len >= *buflen) {
10125                 char *newbuf;
10126                 *buflen *= 2;
10127                 *buflen += len;
10128                 newbuf = g_realloc (buffer, *buflen);
10129                 p = newbuf + (p-buffer);
10130                 buffer = newbuf;
10131         }
10132
10133         encode_field_or_prop_type (type, p, &p);
10134
10135         len = strlen (name);
10136         mono_metadata_encode_value (len, p, &p);
10137         memcpy (p, name, len);
10138         p += len;
10139         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10140         *retp = p;
10141         *retbuffer = buffer;
10142 }
10143
10144 /*
10145  * mono_reflection_get_custom_attrs_blob:
10146  * @ctor: custom attribute constructor
10147  * @ctorArgs: arguments o the constructor
10148  * @properties:
10149  * @propValues:
10150  * @fields:
10151  * @fieldValues:
10152  * 
10153  * Creates the blob of data that needs to be saved in the metadata and that represents
10154  * the custom attributed described by @ctor, @ctorArgs etc.
10155  * Returns: a Byte array representing the blob of data.
10156  */
10157 MonoArray*
10158 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10159 {
10160         MonoArray *result;
10161         MonoMethodSignature *sig;
10162         MonoObject *arg;
10163         char *buffer, *p;
10164         guint32 buflen, i;
10165
10166         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10167                 /* sig is freed later so allocate it in the heap */
10168                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10169         } else {
10170                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10171         }
10172
10173         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10174         buflen = 256;
10175         p = buffer = g_malloc (buflen);
10176         /* write the prolog */
10177         *p++ = 1;
10178         *p++ = 0;
10179         for (i = 0; i < sig->param_count; ++i) {
10180                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10181                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10182         }
10183         i = 0;
10184         if (properties)
10185                 i += mono_array_length (properties);
10186         if (fields)
10187                 i += mono_array_length (fields);
10188         *p++ = i & 0xff;
10189         *p++ = (i >> 8) & 0xff;
10190         if (properties) {
10191                 MonoObject *prop;
10192                 for (i = 0; i < mono_array_length (properties); ++i) {
10193                         MonoType *ptype;
10194                         char *pname;
10195
10196                         prop = mono_array_get (properties, gpointer, i);
10197                         get_prop_name_and_type (prop, &pname, &ptype);
10198                         *p++ = 0x54; /* PROPERTY signature */
10199                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10200                         g_free (pname);
10201                 }
10202         }
10203
10204         if (fields) {
10205                 MonoObject *field;
10206                 for (i = 0; i < mono_array_length (fields); ++i) {
10207                         MonoType *ftype;
10208                         char *fname;
10209
10210                         field = mono_array_get (fields, gpointer, i);
10211                         get_field_name_and_type (field, &fname, &ftype);
10212                         *p++ = 0x53; /* FIELD signature */
10213                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10214                         g_free (fname);
10215                 }
10216         }
10217
10218         g_assert (p - buffer <= buflen);
10219         buflen = p - buffer;
10220         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10221         p = mono_array_addr (result, char, 0);
10222         memcpy (p, buffer, buflen);
10223         g_free (buffer);
10224         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10225                 g_free (sig);
10226         return result;
10227 }
10228
10229 /*
10230  * mono_reflection_setup_internal_class:
10231  * @tb: a TypeBuilder object
10232  *
10233  * Creates a MonoClass that represents the TypeBuilder.
10234  * This is a trick that lets us simplify a lot of reflection code
10235  * (and will allow us to support Build and Run assemblies easier).
10236  */
10237 void
10238 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10239 {
10240         MonoError error;
10241         MonoClass *klass, *parent;
10242
10243         RESOLVE_TYPE (tb->parent);
10244
10245         mono_loader_lock ();
10246
10247         if (tb->parent) {
10248                 /* check so we can compile corlib correctly */
10249                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10250                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10251                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10252                 } else {
10253                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10254                 }
10255         } else {
10256                 parent = NULL;
10257         }
10258         
10259         /* the type has already being created: it means we just have to change the parent */
10260         if (tb->type.type) {
10261                 klass = mono_class_from_mono_type (tb->type.type);
10262                 klass->parent = NULL;
10263                 /* fool mono_class_setup_parent */
10264                 klass->supertypes = NULL;
10265                 mono_class_setup_parent (klass, parent);
10266                 mono_class_setup_mono_type (klass);
10267                 mono_loader_unlock ();
10268                 return;
10269         }
10270
10271         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10272
10273         klass->image = &tb->module->dynamic_image->image;
10274
10275         klass->inited = 1; /* we lie to the runtime */
10276         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10277         if (!mono_error_ok (&error))
10278                 goto failure;
10279         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10280         if (!mono_error_ok (&error))
10281                 goto failure;
10282         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10283         klass->flags = tb->attrs;
10284         
10285         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10286
10287         klass->element_class = klass;
10288
10289         if (mono_class_get_ref_info (klass) == NULL) {
10290
10291                 mono_class_set_ref_info (klass, tb);
10292
10293                 /* Put into cache so mono_class_get_checked () will find it.
10294                 Skip nested types as those should not be available on the global scope. */
10295                 if (!tb->nesting_type)
10296                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10297
10298                 /*
10299                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10300                 by performing a mono_class_get which does the full resolution.
10301
10302                 Working around this semantics would require us to write a lot of code for no clear advantage.
10303                 */
10304                 mono_image_append_class_to_reflection_info_set (klass);
10305         } else {
10306                 g_assert (mono_class_get_ref_info (klass) == tb);
10307         }
10308
10309         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10310
10311         if (parent != NULL) {
10312                 mono_class_setup_parent (klass, parent);
10313         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10314                 const char *old_n = klass->name;
10315                 /* trick to get relative numbering right when compiling corlib */
10316                 klass->name = "BuildingObject";
10317                 mono_class_setup_parent (klass, mono_defaults.object_class);
10318                 klass->name = old_n;
10319         }
10320
10321         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10322                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10323                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10324                 klass->instance_size = sizeof (MonoObject);
10325                 klass->size_inited = 1;
10326                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10327         }
10328
10329         mono_class_setup_mono_type (klass);
10330
10331         mono_class_setup_supertypes (klass);
10332
10333         /*
10334          * FIXME: handle interfaces.
10335          */
10336
10337         tb->type.type = &klass->byval_arg;
10338
10339         if (tb->nesting_type) {
10340                 g_assert (tb->nesting_type->type);
10341                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10342         }
10343
10344         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10345
10346         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10347         
10348         mono_loader_unlock ();
10349         return;
10350
10351 failure:
10352         mono_loader_unlock ();
10353         mono_error_raise_exception (&error);
10354 }
10355
10356 /*
10357  * mono_reflection_setup_generic_class:
10358  * @tb: a TypeBuilder object
10359  *
10360  * Setup the generic class before adding the first generic parameter.
10361  */
10362 void
10363 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10364 {
10365 }
10366
10367 /*
10368  * mono_reflection_create_generic_class:
10369  * @tb: a TypeBuilder object
10370  *
10371  * Creates the generic class after all generic parameters have been added.
10372  */
10373 void
10374 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10375 {
10376         MonoClass *klass;
10377         int count, i;
10378
10379         klass = mono_class_from_mono_type (tb->type.type);
10380
10381         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10382
10383         if (klass->generic_container || (count == 0))
10384                 return;
10385
10386         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10387
10388         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10389
10390         klass->generic_container->owner.klass = klass;
10391         klass->generic_container->type_argc = count;
10392         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10393
10394         klass->is_generic = 1;
10395
10396         for (i = 0; i < count; i++) {
10397                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10398                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10399                 klass->generic_container->type_params [i] = *param;
10400                 /*Make sure we are a diferent type instance */
10401                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10402                 klass->generic_container->type_params [i].info.pklass = NULL;
10403                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10404
10405                 g_assert (klass->generic_container->type_params [i].param.owner);
10406         }
10407
10408         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10409 }
10410
10411 /*
10412  * mono_reflection_create_internal_class:
10413  * @tb: a TypeBuilder object
10414  *
10415  * Actually create the MonoClass that is associated with the TypeBuilder.
10416  */
10417 void
10418 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10419 {
10420         MonoClass *klass;
10421
10422         klass = mono_class_from_mono_type (tb->type.type);
10423
10424         mono_loader_lock ();
10425         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10426                 MonoReflectionFieldBuilder *fb;
10427                 MonoClass *ec;
10428                 MonoType *enum_basetype;
10429
10430                 g_assert (tb->fields != NULL);
10431                 g_assert (mono_array_length (tb->fields) >= 1);
10432
10433                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10434
10435                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10436                         mono_loader_unlock ();
10437                         return;
10438                 }
10439
10440                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10441                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10442                 if (!klass->element_class)
10443                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10444
10445                 /*
10446                  * get the element_class from the current corlib.
10447                  */
10448                 ec = default_class_from_mono_type (enum_basetype);
10449                 klass->instance_size = ec->instance_size;
10450                 klass->size_inited = 1;
10451                 /* 
10452                  * this is almost safe to do with enums and it's needed to be able
10453                  * to create objects of the enum type (for use in SetConstant).
10454                  */
10455                 /* FIXME: Does this mean enums can't have method overrides ? */
10456                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10457         }
10458         mono_loader_unlock ();
10459 }
10460
10461 static MonoMarshalSpec*
10462 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10463                                                                 MonoReflectionMarshal *minfo)
10464 {
10465         MonoMarshalSpec *res;
10466
10467         res = image_g_new0 (image, MonoMarshalSpec, 1);
10468         res->native = minfo->type;
10469
10470         switch (minfo->type) {
10471         case MONO_NATIVE_LPARRAY:
10472                 res->data.array_data.elem_type = minfo->eltype;
10473                 if (minfo->has_size) {
10474                         res->data.array_data.param_num = minfo->param_num;
10475                         res->data.array_data.num_elem = minfo->count;
10476                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10477                 }
10478                 else {
10479                         res->data.array_data.param_num = -1;
10480                         res->data.array_data.num_elem = -1;
10481                         res->data.array_data.elem_mult = -1;
10482                 }
10483                 break;
10484
10485         case MONO_NATIVE_BYVALTSTR:
10486         case MONO_NATIVE_BYVALARRAY:
10487                 res->data.array_data.num_elem = minfo->count;
10488                 break;
10489
10490         case MONO_NATIVE_CUSTOM:
10491                 if (minfo->marshaltyperef)
10492                         res->data.custom_data.custom_name =
10493                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10494                 if (minfo->mcookie)
10495                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10496                 break;
10497
10498         default:
10499                 break;
10500         }
10501
10502         return res;
10503 }
10504 #endif /* !DISABLE_REFLECTION_EMIT */
10505
10506 MonoReflectionMarshalAsAttribute*
10507 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10508                                                                                    MonoMarshalSpec *spec)
10509 {
10510         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10511         MonoReflectionMarshalAsAttribute *minfo;
10512         MonoType *mtype;
10513
10514         if (!System_Reflection_Emit_MarshalAsAttribute) {
10515                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10516                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10517                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10518         }
10519
10520         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10521         minfo->utype = spec->native;
10522
10523         switch (minfo->utype) {
10524         case MONO_NATIVE_LPARRAY:
10525                 minfo->array_subtype = spec->data.array_data.elem_type;
10526                 minfo->size_const = spec->data.array_data.num_elem;
10527                 if (spec->data.array_data.param_num != -1)
10528                         minfo->size_param_index = spec->data.array_data.param_num;
10529                 break;
10530
10531         case MONO_NATIVE_BYVALTSTR:
10532         case MONO_NATIVE_BYVALARRAY:
10533                 minfo->size_const = spec->data.array_data.num_elem;
10534                 break;
10535
10536         case MONO_NATIVE_CUSTOM:
10537                 if (spec->data.custom_data.custom_name) {
10538                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10539                         if (mtype)
10540                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10541
10542                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10543                 }
10544                 if (spec->data.custom_data.cookie)
10545                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10546                 break;
10547
10548         default:
10549                 break;
10550         }
10551
10552         return minfo;
10553 }
10554
10555 #ifndef DISABLE_REFLECTION_EMIT
10556 static MonoMethod*
10557 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10558                                          ReflectionMethodBuilder *rmb,
10559                                          MonoMethodSignature *sig)
10560 {
10561         MonoError error;
10562         MonoMethod *m;
10563         MonoMethodWrapper *wrapperm;
10564         MonoMarshalSpec **specs;
10565         MonoReflectionMethodAux *method_aux;
10566         MonoImage *image;
10567         gboolean dynamic;
10568         int i;
10569
10570         mono_error_init (&error);
10571         /*
10572          * Methods created using a MethodBuilder should have their memory allocated
10573          * inside the image mempool, while dynamic methods should have their memory
10574          * malloc'd.
10575          */
10576         dynamic = rmb->refs != NULL;
10577         image = dynamic ? NULL : klass->image;
10578
10579         if (!dynamic)
10580                 g_assert (!klass->generic_class);
10581
10582         mono_loader_lock ();
10583
10584         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10585                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10586                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10587         else
10588                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10589
10590         wrapperm = (MonoMethodWrapper*)m;
10591
10592         m->dynamic = dynamic;
10593         m->slot = -1;
10594         m->flags = rmb->attrs;
10595         m->iflags = rmb->iattrs;
10596         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10597         m->klass = klass;
10598         m->signature = sig;
10599         m->sre_method = TRUE;
10600         m->skip_visibility = rmb->skip_visibility;
10601         if (rmb->table_idx)
10602                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10603
10604         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10605                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10606                         m->string_ctor = 1;
10607
10608                 m->signature->pinvoke = 1;
10609         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10610                 m->signature->pinvoke = 1;
10611
10612                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10613
10614                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10615                 g_assert (mono_error_ok (&error));
10616                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10617                 g_assert (mono_error_ok (&error));
10618                 
10619                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10620
10621                 if (image_is_dynamic (klass->image))
10622                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10623
10624                 mono_loader_unlock ();
10625
10626                 return m;
10627         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10628                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10629                 MonoMethodHeader *header;
10630                 guint32 code_size;
10631                 gint32 max_stack, i;
10632                 gint32 num_locals = 0;
10633                 gint32 num_clauses = 0;
10634                 guint8 *code;
10635
10636                 if (rmb->ilgen) {
10637                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10638                         code_size = rmb->ilgen->code_len;
10639                         max_stack = rmb->ilgen->max_stack;
10640                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10641                         if (rmb->ilgen->ex_handlers)
10642                                 num_clauses = method_count_clauses (rmb->ilgen);
10643                 } else {
10644                         if (rmb->code) {
10645                                 code = mono_array_addr (rmb->code, guint8, 0);
10646                                 code_size = mono_array_length (rmb->code);
10647                                 /* we probably need to run a verifier on the code... */
10648                                 max_stack = 8; 
10649                         }
10650                         else {
10651                                 code = NULL;
10652                                 code_size = 0;
10653                                 max_stack = 8;
10654                         }
10655                 }
10656
10657                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10658                 header->code_size = code_size;
10659                 header->code = image_g_malloc (image, code_size);
10660                 memcpy ((char*)header->code, code, code_size);
10661                 header->max_stack = max_stack;
10662                 header->init_locals = rmb->init_locals;
10663                 header->num_locals = num_locals;
10664
10665                 for (i = 0; i < num_locals; ++i) {
10666                         MonoReflectionLocalBuilder *lb = 
10667                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10668
10669                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10670                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10671                 }
10672
10673                 header->num_clauses = num_clauses;
10674                 if (num_clauses) {
10675                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10676                                  rmb->ilgen, num_clauses);
10677                 }
10678
10679                 wrapperm->header = header;
10680         }
10681
10682         if (rmb->generic_params) {
10683                 int count = mono_array_length (rmb->generic_params);
10684                 MonoGenericContainer *container = rmb->generic_container;
10685
10686                 g_assert (container);
10687
10688                 container->type_argc = count;
10689                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10690                 container->owner.method = m;
10691
10692                 m->is_generic = TRUE;
10693                 mono_method_set_generic_container (m, container);
10694
10695                 for (i = 0; i < count; i++) {
10696                         MonoReflectionGenericParam *gp =
10697                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10698                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10699                         container->type_params [i] = *param;
10700                 }
10701
10702                 /*
10703                  * The method signature might have pointers to generic parameters that belong to other methods.
10704                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10705                  * generic parameters.
10706                  */
10707                 for (i = 0; i < m->signature->param_count; ++i) {
10708                         MonoType *t = m->signature->params [i];
10709                         if (t->type == MONO_TYPE_MVAR) {
10710                                 MonoGenericParam *gparam =  t->data.generic_param;
10711                                 if (gparam->num < count) {
10712                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10713                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10714                                 }
10715
10716                         }
10717                 }
10718
10719                 if (klass->generic_container) {
10720                         container->parent = klass->generic_container;
10721                         container->context.class_inst = klass->generic_container->context.class_inst;
10722                 }
10723                 container->context.method_inst = mono_get_shared_generic_inst (container);
10724         }
10725
10726         if (rmb->refs) {
10727                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10728                 int i;
10729                 void **data;
10730
10731                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10732
10733                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10734                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10735                 for (i = 0; i < rmb->nrefs; ++i)
10736                         data [i + 1] = rmb->refs [i];
10737         }
10738
10739         method_aux = NULL;
10740
10741         /* Parameter info */
10742         if (rmb->pinfo) {
10743                 if (!method_aux)
10744                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10745                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10746                 for (i = 0; i <= m->signature->param_count; ++i) {
10747                         MonoReflectionParamBuilder *pb;
10748                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10749                                 if ((i > 0) && (pb->attrs)) {
10750                                         /* Make a copy since it might point to a shared type structure */
10751                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10752                                         m->signature->params [i - 1]->attrs = pb->attrs;
10753                                 }
10754
10755                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10756                                         MonoDynamicImage *assembly;
10757                                         guint32 idx, def_type, len;
10758                                         char *p;
10759                                         const char *p2;
10760
10761                                         if (!method_aux->param_defaults) {
10762                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10763                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10764                                         }
10765                                         assembly = (MonoDynamicImage*)klass->image;
10766                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10767                                         /* Copy the data from the blob since it might get realloc-ed */
10768                                         p = assembly->blob.data + idx;
10769                                         len = mono_metadata_decode_blob_size (p, &p2);
10770                                         len += p2 - p;
10771                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10772                                         method_aux->param_default_types [i] = def_type;
10773                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10774                                 }
10775
10776                                 if (pb->name) {
10777                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10778                                         g_assert (mono_error_ok (&error));
10779                                 }
10780                                 if (pb->cattrs) {
10781                                         if (!method_aux->param_cattr)
10782                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10783                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10784                                 }
10785                         }
10786                 }
10787         }
10788
10789         /* Parameter marshalling */
10790         specs = NULL;
10791         if (rmb->pinfo)         
10792                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10793                         MonoReflectionParamBuilder *pb;
10794                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10795                                 if (pb->marshal_info) {
10796                                         if (specs == NULL)
10797                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10798                                         specs [pb->position] = 
10799                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10800                                 }
10801                         }
10802                 }
10803         if (specs != NULL) {
10804                 if (!method_aux)
10805                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10806                 method_aux->param_marshall = specs;
10807         }
10808
10809         if (image_is_dynamic (klass->image) && method_aux)
10810                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10811
10812         mono_loader_unlock ();
10813
10814         return m;
10815 }       
10816
10817 static MonoMethod*
10818 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10819 {
10820         ReflectionMethodBuilder rmb;
10821         MonoMethodSignature *sig;
10822
10823         mono_loader_lock ();
10824         sig = ctor_builder_to_signature (klass->image, mb);
10825         mono_loader_unlock ();
10826
10827         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10828
10829         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10830         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10831
10832         /* If we are in a generic class, we might be called multiple times from inflate_method */
10833         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10834                 /* ilgen is no longer needed */
10835                 mb->ilgen = NULL;
10836         }
10837
10838         return mb->mhandle;
10839 }
10840
10841 static MonoMethod*
10842 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10843 {
10844         ReflectionMethodBuilder rmb;
10845         MonoMethodSignature *sig;
10846
10847         mono_loader_lock ();
10848         sig = method_builder_to_signature (klass->image, mb);
10849         mono_loader_unlock ();
10850
10851         reflection_methodbuilder_from_method_builder (&rmb, mb);
10852
10853         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10854         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10855
10856         /* If we are in a generic class, we might be called multiple times from inflate_method */
10857         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10858                 /* ilgen is no longer needed */
10859                 mb->ilgen = NULL;
10860         }
10861         return mb->mhandle;
10862 }
10863
10864 static MonoClassField*
10865 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10866 {
10867         MonoClassField *field;
10868         MonoType *custom;
10869         MonoError error;
10870
10871         field = g_new0 (MonoClassField, 1);
10872
10873         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10874         g_assert (mono_error_ok (&error));
10875         if (fb->attrs || fb->modreq || fb->modopt) {
10876                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10877                 field->type->attrs = fb->attrs;
10878
10879                 g_assert (image_is_dynamic (klass->image));
10880                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10881                 g_free (field->type);
10882                 field->type = mono_metadata_type_dup (klass->image, custom);
10883                 g_free (custom);
10884         } else {
10885                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10886         }
10887         if (fb->offset != -1)
10888                 field->offset = fb->offset;
10889         field->parent = klass;
10890         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10891
10892         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10893
10894         return field;
10895 }
10896 #endif
10897
10898 MonoType*
10899 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10900 {
10901         MonoClass *klass;
10902         MonoReflectionTypeBuilder *tb = NULL;
10903         gboolean is_dynamic = FALSE;
10904         MonoClass *geninst;
10905
10906         mono_loader_lock ();
10907
10908         if (is_sre_type_builder (mono_object_class (type))) {
10909                 tb = (MonoReflectionTypeBuilder *) type;
10910
10911                 is_dynamic = TRUE;
10912         } else if (is_sre_generic_instance (mono_object_class (type))) {
10913                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10914                 MonoReflectionType *gtd = rgi->generic_type;
10915
10916                 if (is_sre_type_builder (mono_object_class (gtd))) {
10917                         tb = (MonoReflectionTypeBuilder *)gtd;
10918                         is_dynamic = TRUE;
10919                 }
10920         }
10921
10922         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10923         if (tb && tb->generic_container)
10924                 mono_reflection_create_generic_class (tb);
10925
10926         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10927         if (!klass->generic_container) {
10928                 mono_loader_unlock ();
10929                 return NULL;
10930         }
10931
10932         if (klass->wastypebuilder) {
10933                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10934
10935                 is_dynamic = TRUE;
10936         }
10937
10938         mono_loader_unlock ();
10939
10940         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10941
10942         return &geninst->byval_arg;
10943 }
10944
10945 MonoClass*
10946 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10947 {
10948         MonoGenericClass *gclass;
10949         MonoGenericInst *inst;
10950
10951         g_assert (klass->generic_container);
10952
10953         inst = mono_metadata_get_generic_inst (type_argc, types);
10954         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10955
10956         return mono_generic_class_get_class (gclass);
10957 }
10958
10959 MonoReflectionMethod*
10960 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10961 {
10962         MonoError error;
10963         MonoClass *klass;
10964         MonoMethod *method, *inflated;
10965         MonoMethodInflated *imethod;
10966         MonoGenericContext tmp_context;
10967         MonoGenericInst *ginst;
10968         MonoType **type_argv;
10969         int count, i;
10970
10971         /*FIXME but this no longer should happen*/
10972         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10973 #ifndef DISABLE_REFLECTION_EMIT
10974                 MonoReflectionMethodBuilder *mb = NULL;
10975                 MonoReflectionTypeBuilder *tb;
10976                 MonoClass *klass;
10977
10978                 mb = (MonoReflectionMethodBuilder *) rmethod;
10979                 tb = (MonoReflectionTypeBuilder *) mb->type;
10980                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10981
10982                 method = methodbuilder_to_mono_method (klass, mb);
10983 #else
10984                 g_assert_not_reached ();
10985                 method = NULL;
10986 #endif
10987         } else {
10988                 method = rmethod->method;
10989         }
10990
10991         klass = method->klass;
10992
10993         if (method->is_inflated)
10994                 method = ((MonoMethodInflated *) method)->declaring;
10995
10996         count = mono_method_signature (method)->generic_param_count;
10997         if (count != mono_array_length (types))
10998                 return NULL;
10999
11000         type_argv = g_new0 (MonoType *, count);
11001         for (i = 0; i < count; i++) {
11002                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
11003                 type_argv [i] = mono_reflection_type_get_handle (garg);
11004         }
11005         ginst = mono_metadata_get_generic_inst (count, type_argv);
11006         g_free (type_argv);
11007
11008         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11009         tmp_context.method_inst = ginst;
11010
11011         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11012         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11013         imethod = (MonoMethodInflated *) inflated;
11014
11015         /*FIXME but I think this is no longer necessary*/
11016         if (image_is_dynamic (method->klass->image)) {
11017                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11018                 /*
11019                  * This table maps metadata structures representing inflated methods/fields
11020                  * to the reflection objects representing their generic definitions.
11021                  */
11022                 mono_image_lock ((MonoImage*)image);
11023                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11024                 mono_image_unlock ((MonoImage*)image);
11025         }
11026
11027         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11028                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11029         
11030         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
11031 }
11032
11033 #ifndef DISABLE_REFLECTION_EMIT
11034
11035 static MonoMethod *
11036 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11037 {
11038         MonoMethodInflated *imethod;
11039         MonoGenericContext *context;
11040         int i;
11041
11042         /*
11043          * With generic code sharing the klass might not be inflated.
11044          * This can happen because classes inflated with their own
11045          * type arguments are "normalized" to the uninflated class.
11046          */
11047         if (!klass->generic_class)
11048                 return method;
11049
11050         context = mono_class_get_context (klass);
11051
11052         if (klass->method.count && klass->methods) {
11053                 /* Find the already created inflated method */
11054                 for (i = 0; i < klass->method.count; ++i) {
11055                         g_assert (klass->methods [i]->is_inflated);
11056                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11057                                 break;
11058                 }
11059                 g_assert (i < klass->method.count);
11060                 imethod = (MonoMethodInflated*)klass->methods [i];
11061         } else {
11062                 MonoError error;
11063                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11064                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11065         }
11066
11067         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11068                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11069
11070                 mono_image_lock ((MonoImage*)image);
11071                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11072                 mono_image_unlock ((MonoImage*)image);
11073         }
11074         return (MonoMethod *) imethod;
11075 }
11076
11077 static MonoMethod *
11078 inflate_method (MonoReflectionType *type, MonoObject *obj)
11079 {
11080         MonoMethod *method;
11081         MonoClass *gklass;
11082
11083         MonoClass *type_class = mono_object_class (type);
11084
11085         if (is_sre_generic_instance (type_class)) {
11086                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11087                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11088         } else if (is_sre_type_builder (type_class)) {
11089                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11090         } else if (type->type) {
11091                 gklass = mono_class_from_mono_type (type->type);
11092                 gklass = mono_class_get_generic_type_definition (gklass);
11093         } else {
11094                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11095         }
11096
11097         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11098                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11099                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11100                 else
11101                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11102         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11103                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11104         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11105                 method = ((MonoReflectionMethod *) obj)->method;
11106         else {
11107                 method = NULL; /* prevent compiler warning */
11108                 g_error ("can't handle type %s", obj->vtable->klass->name);
11109         }
11110
11111         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11112 }
11113
11114 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11115 void
11116 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11117 {
11118         MonoGenericClass *gclass;
11119         MonoDynamicGenericClass *dgclass;
11120         MonoClass *klass, *gklass;
11121         MonoType *gtype;
11122         int i;
11123
11124         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11125         klass = mono_class_from_mono_type (gtype);
11126         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11127         gclass = gtype->data.generic_class;
11128
11129         if (!gclass->is_dynamic)
11130                 return;
11131
11132         dgclass = (MonoDynamicGenericClass *) gclass;
11133
11134         if (dgclass->initialized)
11135                 return;
11136
11137         gklass = gclass->container_class;
11138         mono_class_init (gklass);
11139
11140         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11141
11142         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11143         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11144         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11145
11146         for (i = 0; i < dgclass->count_fields; i++) {
11147                 MonoObject *obj = mono_array_get (fields, gpointer, i);
11148                 MonoClassField *field, *inflated_field = NULL;
11149
11150                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11151                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11152                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11153                         field = ((MonoReflectionField *) obj)->field;
11154                 else {
11155                         field = NULL; /* prevent compiler warning */
11156                         g_assert_not_reached ();
11157                 }
11158
11159                 dgclass->fields [i] = *field;
11160                 dgclass->fields [i].parent = klass;
11161                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11162                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11163                 dgclass->field_generic_types [i] = field->type;
11164                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11165                 dgclass->field_objects [i] = obj;
11166
11167                 if (inflated_field) {
11168                         g_free (inflated_field);
11169                 } else {
11170                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11171                 }
11172         }
11173
11174         dgclass->initialized = TRUE;
11175 }
11176
11177 void
11178 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11179 {
11180         MonoDynamicGenericClass *dgclass;
11181         int i;
11182
11183         g_assert (gclass->is_dynamic);
11184
11185         dgclass = (MonoDynamicGenericClass *)gclass;
11186
11187         for (i = 0; i < dgclass->count_fields; ++i) {
11188                 MonoClassField *field = dgclass->fields + i;
11189                 mono_metadata_free_type (field->type);
11190                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11191         }
11192 }
11193
11194 static void
11195 fix_partial_generic_class (MonoClass *klass)
11196 {
11197         MonoClass *gklass = klass->generic_class->container_class;
11198         MonoDynamicGenericClass *dgclass;
11199         int i;
11200
11201         if (klass->wastypebuilder)
11202                 return;
11203
11204         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11205         if (klass->parent != gklass->parent) {
11206                 MonoError error;
11207                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11208                 if (mono_error_ok (&error)) {
11209                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11210                         mono_metadata_free_type (parent_type);
11211                         if (parent != klass->parent) {
11212                                 /*fool mono_class_setup_parent*/
11213                                 klass->supertypes = NULL;
11214                                 mono_class_setup_parent (klass, parent);
11215                         }
11216                 } else {
11217                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11218                         mono_error_cleanup (&error);
11219                         if (gklass->wastypebuilder)
11220                                 klass->wastypebuilder = TRUE;
11221                         return;
11222                 }
11223         }
11224
11225         if (!dgclass->initialized)
11226                 return;
11227
11228         if (klass->method.count != gklass->method.count) {
11229                 klass->method.count = gklass->method.count;
11230                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11231
11232                 for (i = 0; i < klass->method.count; i++) {
11233                         MonoError error;
11234                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11235                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11236                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11237                 }
11238         }
11239
11240         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11241                 klass->interface_count = gklass->interface_count;
11242                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11243                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11244
11245                 for (i = 0; i < gklass->interface_count; ++i) {
11246                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11247                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11248                         mono_metadata_free_type (iface_type);
11249
11250                         ensure_runtime_vtable (klass->interfaces [i]);
11251                 }
11252                 klass->interfaces_inited = 1;
11253         }
11254
11255         if (klass->field.count != gklass->field.count) {
11256                 klass->field.count = gklass->field.count;
11257                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11258
11259                 for (i = 0; i < klass->field.count; i++) {
11260                         klass->fields [i] = gklass->fields [i];
11261                         klass->fields [i].parent = klass;
11262                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11263                 }
11264         }
11265
11266         /*We can only finish with this klass once it's parent has as well*/
11267         if (gklass->wastypebuilder)
11268                 klass->wastypebuilder = TRUE;
11269         return;
11270 }
11271
11272 static void
11273 ensure_generic_class_runtime_vtable (MonoClass *klass)
11274 {
11275         MonoClass *gklass = klass->generic_class->container_class;
11276
11277         ensure_runtime_vtable (gklass); 
11278
11279         fix_partial_generic_class (klass);
11280 }
11281
11282 static void
11283 ensure_runtime_vtable (MonoClass *klass)
11284 {
11285         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11286         int i, num, j;
11287
11288         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11289                 return;
11290         if (klass->parent)
11291                 ensure_runtime_vtable (klass->parent);
11292
11293         if (tb) {
11294                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11295                 num += tb->num_methods;
11296                 klass->method.count = num;
11297                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11298                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11299                 for (i = 0; i < num; ++i)
11300                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11301                 num = tb->num_methods;
11302                 j = i;
11303                 for (i = 0; i < num; ++i)
11304                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11305         
11306                 if (tb->interfaces) {
11307                         klass->interface_count = mono_array_length (tb->interfaces);
11308                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11309                         for (i = 0; i < klass->interface_count; ++i) {
11310                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11311                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11312                                 ensure_runtime_vtable (klass->interfaces [i]);
11313                         }
11314                         klass->interfaces_inited = 1;
11315                 }
11316         } else if (klass->generic_class){
11317                 ensure_generic_class_runtime_vtable (klass);
11318         }
11319
11320         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11321                 int slot_num = 0;
11322                 for (i = 0; i < klass->method.count; ++i) {
11323                         MonoMethod *im = klass->methods [i];
11324                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11325                                 im->slot = slot_num++;
11326                 }
11327                 
11328                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11329                 mono_class_setup_interface_offsets (klass);
11330                 mono_class_setup_interface_id (klass);
11331         }
11332
11333         /*
11334          * The generic vtable is needed even if image->run is not set since some
11335          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11336          * method->slot being defined.
11337          */
11338
11339         /* 
11340          * tb->methods could not be freed since it is used for determining 
11341          * overrides during dynamic vtable construction.
11342          */
11343 }
11344
11345 static MonoMethod*
11346 mono_reflection_method_get_handle (MonoObject *method)
11347 {
11348         MonoClass *klass = mono_object_class (method);
11349         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11350                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11351                 return sr_method->method;
11352         }
11353         if (is_sre_method_builder (klass)) {
11354                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11355                 return mb->mhandle;
11356         }
11357         if (is_sre_method_on_tb_inst (klass)) {
11358                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11359                 MonoMethod *result;
11360                 /*FIXME move this to a proper method and unify with resolve_object*/
11361                 if (m->method_args) {
11362                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11363                 } else {
11364                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11365                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11366                         MonoMethod *mono_method;
11367
11368                         if (is_sre_method_builder (mono_object_class (m->mb)))
11369                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11370                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11371                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11372                         else
11373                                 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)));
11374
11375                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11376                 }
11377                 return result;
11378         }
11379
11380         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
11381         return NULL;
11382 }
11383
11384 void
11385 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11386 {
11387         MonoReflectionTypeBuilder *tb;
11388         int i, j, onum;
11389         MonoReflectionMethod *m;
11390
11391         *overrides = NULL;
11392         *num_overrides = 0;
11393
11394         g_assert (image_is_dynamic (klass->image));
11395
11396         if (!mono_class_get_ref_info (klass))
11397                 return;
11398
11399         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11400
11401         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11402
11403         onum = 0;
11404         if (tb->methods) {
11405                 for (i = 0; i < tb->num_methods; ++i) {
11406                         MonoReflectionMethodBuilder *mb = 
11407                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11408                         if (mb->override_methods)
11409                                 onum += mono_array_length (mb->override_methods);
11410                 }
11411         }
11412
11413         if (onum) {
11414                 *overrides = g_new0 (MonoMethod*, onum * 2);
11415
11416                 onum = 0;
11417                 for (i = 0; i < tb->num_methods; ++i) {
11418                         MonoReflectionMethodBuilder *mb = 
11419                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11420                         if (mb->override_methods) {
11421                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11422                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11423
11424                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11425                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11426
11427                                         g_assert (mb->mhandle);
11428
11429                                         onum ++;
11430                                 }
11431                         }
11432                 }
11433         }
11434
11435         *num_overrides = onum;
11436 }
11437
11438 static void
11439 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11440 {
11441         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11442         MonoReflectionFieldBuilder *fb;
11443         MonoClassField *field;
11444         MonoImage *image = klass->image;
11445         const char *p, *p2;
11446         int i;
11447         guint32 len, idx, real_size = 0;
11448
11449         klass->field.count = tb->num_fields;
11450         klass->field.first = 0;
11451
11452         mono_error_init (error);
11453
11454         if (tb->class_size) {
11455                 if ((tb->packing_size & 0xffffff00) != 0) {
11456                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11457                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11458                         return;
11459                 }
11460                 klass->packing_size = tb->packing_size;
11461                 real_size = klass->instance_size + tb->class_size;
11462         }
11463
11464         if (!klass->field.count) {
11465                 klass->instance_size = MAX (klass->instance_size, real_size);
11466                 return;
11467         }
11468         
11469         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11470         mono_class_alloc_ext (klass);
11471         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11472         /*
11473         This is, guess what, a hack.
11474         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11475         On the static path no field class is resolved, only types are built. This is the right thing to do
11476         but we suck.
11477         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11478         */
11479         klass->size_inited = 1;
11480
11481         for (i = 0; i < klass->field.count; ++i) {
11482                 MonoArray *rva_data;
11483                 fb = mono_array_get (tb->fields, gpointer, i);
11484                 field = &klass->fields [i];
11485                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11486                 if (!mono_error_ok (error))
11487                         return;
11488                 if (fb->attrs) {
11489                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11490                         field->type->attrs = fb->attrs;
11491                 } else {
11492                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11493                 }
11494
11495                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11496                         char *base = mono_array_addr (rva_data, char, 0);
11497                         size_t size = mono_array_length (rva_data);
11498                         char *data = mono_image_alloc (klass->image, size);
11499                         memcpy (data, base, size);
11500                         klass->ext->field_def_values [i].data = data;
11501                 }
11502                 if (fb->offset != -1)
11503                         field->offset = fb->offset;
11504                 field->parent = klass;
11505                 fb->handle = field;
11506                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11507
11508                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11509                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11510                 }
11511                 if (fb->def_value) {
11512                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11513                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11514                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11515                         /* Copy the data from the blob since it might get realloc-ed */
11516                         p = assembly->blob.data + idx;
11517                         len = mono_metadata_decode_blob_size (p, &p2);
11518                         len += p2 - p;
11519                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11520                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11521                 }
11522         }
11523
11524         klass->instance_size = MAX (klass->instance_size, real_size);
11525         mono_class_layout_fields (klass);
11526 }
11527
11528 static void
11529 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11530 {
11531         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11532         MonoReflectionPropertyBuilder *pb;
11533         MonoImage *image = klass->image;
11534         MonoProperty *properties;
11535         int i;
11536
11537         mono_error_init (error);
11538
11539         if (!klass->ext)
11540                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11541
11542         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11543         klass->ext->property.first = 0;
11544
11545         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11546         klass->ext->properties = properties;
11547         for (i = 0; i < klass->ext->property.count; ++i) {
11548                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11549                 properties [i].parent = klass;
11550                 properties [i].attrs = pb->attrs;
11551                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11552                 if (!mono_error_ok (error))
11553                         return;
11554                 if (pb->get_method)
11555                         properties [i].get = pb->get_method->mhandle;
11556                 if (pb->set_method)
11557                         properties [i].set = pb->set_method->mhandle;
11558
11559                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11560                 if (pb->def_value) {
11561                         guint32 len, idx;
11562                         const char *p, *p2;
11563                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11564                         if (!klass->ext->prop_def_values)
11565                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11566                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11567                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11568                         /* Copy the data from the blob since it might get realloc-ed */
11569                         p = assembly->blob.data + idx;
11570                         len = mono_metadata_decode_blob_size (p, &p2);
11571                         len += p2 - p;
11572                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11573                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11574                 }
11575         }
11576 }
11577
11578 MonoReflectionEvent *
11579 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11580 {
11581         MonoEvent *event = g_new0 (MonoEvent, 1);
11582         MonoClass *klass;
11583
11584         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11585
11586         event->parent = klass;
11587         event->attrs = eb->attrs;
11588         event->name = mono_string_to_utf8 (eb->name);
11589         if (eb->add_method)
11590                 event->add = eb->add_method->mhandle;
11591         if (eb->remove_method)
11592                 event->remove = eb->remove_method->mhandle;
11593         if (eb->raise_method)
11594                 event->raise = eb->raise_method->mhandle;
11595
11596 #ifndef MONO_SMALL_CONFIG
11597         if (eb->other_methods) {
11598                 int j;
11599                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11600                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11601                         MonoReflectionMethodBuilder *mb = 
11602                                 mono_array_get (eb->other_methods,
11603                                                 MonoReflectionMethodBuilder*, j);
11604                         event->other [j] = mb->mhandle;
11605                 }
11606         }
11607 #endif
11608
11609         return mono_event_get_object (mono_object_domain (tb), klass, event);
11610 }
11611
11612 static void
11613 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11614 {
11615         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11616         MonoReflectionEventBuilder *eb;
11617         MonoImage *image = klass->image;
11618         MonoEvent *events;
11619         int i;
11620
11621         mono_error_init (error);
11622
11623         if (!klass->ext)
11624                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11625
11626         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11627         klass->ext->event.first = 0;
11628
11629         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11630         klass->ext->events = events;
11631         for (i = 0; i < klass->ext->event.count; ++i) {
11632                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11633                 events [i].parent = klass;
11634                 events [i].attrs = eb->attrs;
11635                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11636                 if (!mono_error_ok (error))
11637                         return;
11638                 if (eb->add_method)
11639                         events [i].add = eb->add_method->mhandle;
11640                 if (eb->remove_method)
11641                         events [i].remove = eb->remove_method->mhandle;
11642                 if (eb->raise_method)
11643                         events [i].raise = eb->raise_method->mhandle;
11644
11645 #ifndef MONO_SMALL_CONFIG
11646                 if (eb->other_methods) {
11647                         int j;
11648                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11649                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11650                                 MonoReflectionMethodBuilder *mb = 
11651                                         mono_array_get (eb->other_methods,
11652                                                                         MonoReflectionMethodBuilder*, j);
11653                                 events [i].other [j] = mb->mhandle;
11654                         }
11655                 }
11656 #endif
11657                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11658         }
11659 }
11660
11661 static gboolean
11662 remove_instantiations_of_and_ensure_contents (gpointer key,
11663                                                   gpointer value,
11664                                                   gpointer user_data)
11665 {
11666         MonoType *type = (MonoType*)key;
11667         MonoClass *klass = (MonoClass*)user_data;
11668
11669         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11670                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11671                 return TRUE;
11672         } else
11673                 return FALSE;
11674 }
11675
11676 static void
11677 check_array_for_usertypes (MonoArray *arr)
11678 {
11679         int i;
11680
11681         if (!arr)
11682                 return;
11683
11684         for (i = 0; i < mono_array_length (arr); ++i)
11685                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11686 }
11687
11688 MonoReflectionType*
11689 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11690 {
11691         MonoError error;
11692         MonoClass *klass;
11693         MonoDomain* domain;
11694         MonoReflectionType* res;
11695         int i, j;
11696
11697         domain = mono_object_domain (tb);
11698         klass = mono_class_from_mono_type (tb->type.type);
11699
11700         /*
11701          * Check for user defined Type subclasses.
11702          */
11703         RESOLVE_TYPE (tb->parent);
11704         check_array_for_usertypes (tb->interfaces);
11705         if (tb->fields) {
11706                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11707                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11708                         if (fb) {
11709                                 RESOLVE_TYPE (fb->type);
11710                                 check_array_for_usertypes (fb->modreq);
11711                                 check_array_for_usertypes (fb->modopt);
11712                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11713                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11714                         }
11715                 }
11716         }
11717         if (tb->methods) {
11718                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11719                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11720                         if (mb) {
11721                                 RESOLVE_TYPE (mb->rtype);
11722                                 check_array_for_usertypes (mb->return_modreq);
11723                                 check_array_for_usertypes (mb->return_modopt);
11724                                 check_array_for_usertypes (mb->parameters);
11725                                 if (mb->param_modreq)
11726                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11727                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11728                                 if (mb->param_modopt)
11729                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11730                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11731                         }
11732                 }
11733         }
11734         if (tb->ctors) {
11735                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11736                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11737                         if (mb) {
11738                                 check_array_for_usertypes (mb->parameters);
11739                                 if (mb->param_modreq)
11740                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11741                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11742                                 if (mb->param_modopt)
11743                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11744                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11745                         }
11746                 }
11747         }
11748
11749         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11750
11751         /* 
11752          * we need to lock the domain because the lock will be taken inside
11753          * So, we need to keep the locking order correct.
11754          */
11755         mono_loader_lock ();
11756         mono_domain_lock (domain);
11757         if (klass->wastypebuilder) {
11758                 mono_domain_unlock (domain);
11759                 mono_loader_unlock ();
11760                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11761         }
11762         /*
11763          * Fields to set in klass:
11764          * the various flags: delegate/unicode/contextbound etc.
11765          */
11766         klass->flags = tb->attrs;
11767         klass->has_cctor = 1;
11768         klass->has_finalize = 1;
11769         klass->has_finalize_inited = 1;
11770
11771         mono_class_setup_parent (klass, klass->parent);
11772         /* fool mono_class_setup_supertypes */
11773         klass->supertypes = NULL;
11774         mono_class_setup_supertypes (klass);
11775         mono_class_setup_mono_type (klass);
11776
11777 #if 0
11778         if (!((MonoDynamicImage*)klass->image)->run) {
11779                 if (klass->generic_container) {
11780                         /* FIXME: The code below can't handle generic classes */
11781                         klass->wastypebuilder = TRUE;
11782                         mono_loader_unlock ();
11783                         mono_domain_unlock (domain);
11784                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11785                 }
11786         }
11787 #endif
11788
11789         /* enums are done right away */
11790         if (!klass->enumtype)
11791                 ensure_runtime_vtable (klass);
11792
11793         if (tb->subtypes) {
11794                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11795                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11796                         mono_class_alloc_ext (klass);
11797                         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)));
11798                 }
11799         }
11800
11801         klass->nested_classes_inited = TRUE;
11802
11803         /* fields and object layout */
11804         if (klass->parent) {
11805                 if (!klass->parent->size_inited)
11806                         mono_class_init (klass->parent);
11807                 klass->instance_size = klass->parent->instance_size;
11808                 klass->sizes.class_size = 0;
11809                 klass->min_align = klass->parent->min_align;
11810                 /* if the type has no fields we won't call the field_setup
11811                  * routine which sets up klass->has_references.
11812                  */
11813                 klass->has_references |= klass->parent->has_references;
11814         } else {
11815                 klass->instance_size = sizeof (MonoObject);
11816                 klass->min_align = 1;
11817         }
11818
11819         /* FIXME: handle packing_size and instance_size */
11820         typebuilder_setup_fields (klass, &error);
11821         if (!mono_error_ok (&error))
11822                 goto failure;
11823         typebuilder_setup_properties (klass, &error);
11824         if (!mono_error_ok (&error))
11825                 goto failure;
11826
11827         typebuilder_setup_events (klass, &error);
11828         if (!mono_error_ok (&error))
11829                 goto failure;
11830
11831         klass->wastypebuilder = TRUE;
11832
11833         /* 
11834          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11835          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11836          * we want to return normal System.MonoType objects, so clear these out from the cache.
11837          *
11838          * Together with this we must ensure the contents of all instances to match the created type.
11839          */
11840         if (domain->type_hash && klass->generic_container)
11841                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11842
11843         mono_domain_unlock (domain);
11844         mono_loader_unlock ();
11845
11846         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11847                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11848                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11849         }
11850
11851         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11852         g_assert (res != (MonoReflectionType*)tb);
11853
11854         return res;
11855
11856 failure:
11857         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11858         klass->wastypebuilder = TRUE;
11859         mono_domain_unlock (domain);
11860         mono_loader_unlock ();
11861         mono_error_raise_exception (&error);
11862         return NULL;
11863 }
11864
11865 void
11866 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11867 {
11868         MonoGenericParamFull *param;
11869         MonoImage *image;
11870         MonoClass *pklass;
11871         MonoError error;
11872
11873         image = &gparam->tbuilder->module->dynamic_image->image;
11874
11875         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11876
11877         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11878         g_assert (mono_error_ok (&error));
11879         param->param.num = gparam->index;
11880
11881         if (gparam->mbuilder) {
11882                 if (!gparam->mbuilder->generic_container) {
11883                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11884                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11885                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11886                         gparam->mbuilder->generic_container->is_method = TRUE;
11887                         /* 
11888                          * Cannot set owner.method, since the MonoMethod is not created yet.
11889                          * Set the image field instead, so type_in_image () works.
11890                          */
11891                         gparam->mbuilder->generic_container->image = klass->image;
11892                 }
11893                 param->param.owner = gparam->mbuilder->generic_container;
11894         } else if (gparam->tbuilder) {
11895                 if (!gparam->tbuilder->generic_container) {
11896                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11897                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11898                         gparam->tbuilder->generic_container->owner.klass = klass;
11899                 }
11900                 param->param.owner = gparam->tbuilder->generic_container;
11901         }
11902
11903         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11904
11905         gparam->type.type = &pklass->byval_arg;
11906
11907         mono_class_set_ref_info (pklass, gparam);
11908         mono_image_append_class_to_reflection_info_set (pklass);
11909 }
11910
11911 MonoArray *
11912 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11913 {
11914         MonoReflectionModuleBuilder *module = sig->module;
11915         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11916         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11917         guint32 buflen, i;
11918         MonoArray *result;
11919         SigBuffer buf;
11920
11921         check_array_for_usertypes (sig->arguments);
11922
11923         sigbuffer_init (&buf, 32);
11924
11925         sigbuffer_add_value (&buf, 0x07);
11926         sigbuffer_add_value (&buf, na);
11927         if (assembly != NULL){
11928                 for (i = 0; i < na; ++i) {
11929                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11930                         encode_reflection_type (assembly, type, &buf);
11931                 }
11932         }
11933
11934         buflen = buf.p - buf.buf;
11935         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11936         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11937         sigbuffer_free (&buf);
11938
11939         return result;
11940 }
11941
11942 MonoArray *
11943 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11944 {
11945         MonoDynamicImage *assembly = sig->module->dynamic_image;
11946         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11947         guint32 buflen, i;
11948         MonoArray *result;
11949         SigBuffer buf;
11950
11951         check_array_for_usertypes (sig->arguments);
11952
11953         sigbuffer_init (&buf, 32);
11954
11955         sigbuffer_add_value (&buf, 0x06);
11956         for (i = 0; i < na; ++i) {
11957                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11958                 encode_reflection_type (assembly, type, &buf);
11959         }
11960
11961         buflen = buf.p - buf.buf;
11962         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11963         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11964         sigbuffer_free (&buf);
11965
11966         return result;
11967 }
11968
11969 typedef struct {
11970         MonoMethod *handle;
11971         MonoDomain *domain;
11972 } DynamicMethodReleaseData;
11973
11974 /*
11975  * The runtime automatically clean up those after finalization.
11976 */      
11977 static MonoReferenceQueue *dynamic_method_queue;
11978
11979 static void
11980 free_dynamic_method (void *dynamic_method)
11981 {
11982         DynamicMethodReleaseData *data = dynamic_method;
11983         MonoDomain *domain = data->domain;
11984         MonoMethod *method = data->handle;
11985         guint32 dis_link;
11986
11987         mono_domain_lock (domain);
11988         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
11989         g_hash_table_remove (domain->method_to_dyn_method, method);
11990         mono_domain_unlock (domain);
11991         g_assert (dis_link);
11992         mono_gchandle_free (dis_link);
11993
11994         mono_runtime_free_method (domain, method);
11995         g_free (data);
11996 }
11997
11998 void 
11999 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12000 {
12001         MonoReferenceQueue *queue;
12002         MonoMethod *handle;
12003         DynamicMethodReleaseData *release_data;
12004         ReflectionMethodBuilder rmb;
12005         MonoMethodSignature *sig;
12006         MonoClass *klass;
12007         MonoDomain *domain;
12008         GSList *l;
12009         int i;
12010
12011         if (mono_runtime_is_shutting_down ())
12012                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12013
12014         if (!(queue = dynamic_method_queue)) {
12015                 mono_loader_lock ();
12016                 if (!(queue = dynamic_method_queue))
12017                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12018                 mono_loader_unlock ();
12019         }
12020
12021         sig = dynamic_method_to_signature (mb);
12022
12023         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12024
12025         /*
12026          * Resolve references.
12027          */
12028         /* 
12029          * Every second entry in the refs array is reserved for storing handle_class,
12030          * which is needed by the ldtoken implementation in the JIT.
12031          */
12032         rmb.nrefs = mb->nrefs;
12033         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12034         for (i = 0; i < mb->nrefs; i += 2) {
12035                 MonoClass *handle_class;
12036                 gpointer ref;
12037                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12038
12039                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12040                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12041                         /*
12042                          * The referenced DynamicMethod should already be created by the managed
12043                          * code, except in the case of circular references. In that case, we store
12044                          * method in the refs array, and fix it up later when the referenced 
12045                          * DynamicMethod is created.
12046                          */
12047                         if (method->mhandle) {
12048                                 ref = method->mhandle;
12049                         } else {
12050                                 /* FIXME: GC object stored in unmanaged memory */
12051                                 ref = method;
12052
12053                                 /* FIXME: GC object stored in unmanaged memory */
12054                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12055                         }
12056                         handle_class = mono_defaults.methodhandle_class;
12057                 } else {
12058                         MonoException *ex = NULL;
12059                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12060                         if (!ref)
12061                                 ex = mono_get_exception_type_load (NULL, NULL);
12062                         else if (mono_security_core_clr_enabled ())
12063                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12064
12065                         if (ex) {
12066                                 g_free (rmb.refs);
12067                                 mono_raise_exception (ex);
12068                                 return;
12069                         }
12070                 }
12071
12072                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12073                 rmb.refs [i + 1] = handle_class;
12074         }               
12075
12076         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12077
12078         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12079         release_data = g_new (DynamicMethodReleaseData, 1);
12080         release_data->handle = handle;
12081         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12082         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12083                 g_free (release_data);
12084
12085         /* Fix up refs entries pointing at us */
12086         for (l = mb->referenced_by; l; l = l->next) {
12087                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12088                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12089                 gpointer *data;
12090                 
12091                 g_assert (method->mhandle);
12092
12093                 data = (gpointer*)wrapper->method_data;
12094                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12095                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12096                                 data [i + 1] = mb->mhandle;
12097                 }
12098         }
12099         g_slist_free (mb->referenced_by);
12100
12101         g_free (rmb.refs);
12102
12103         /* ilgen is no longer needed */
12104         mb->ilgen = NULL;
12105
12106         domain = mono_domain_get ();
12107         mono_domain_lock (domain);
12108         if (!domain->method_to_dyn_method)
12109                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12110         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12111         mono_domain_unlock (domain);
12112 }
12113
12114 #endif /* DISABLE_REFLECTION_EMIT */
12115
12116 /**
12117  * 
12118  * mono_reflection_is_valid_dynamic_token:
12119  * 
12120  * Returns TRUE if token is valid.
12121  * 
12122  */
12123 gboolean
12124 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12125 {
12126         return lookup_dyn_token (image, token) != NULL;
12127 }
12128
12129 MonoMethodSignature *
12130 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12131 {
12132         MonoMethodSignature *sig;
12133         g_assert (image_is_dynamic (image));
12134
12135         mono_error_init (error);
12136
12137         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12138         if (sig)
12139                 return sig;
12140
12141         return mono_method_signature_checked (method, error);
12142 }
12143
12144 #ifndef DISABLE_REFLECTION_EMIT
12145
12146 /**
12147  * mono_reflection_lookup_dynamic_token:
12148  *
12149  * Finish the Builder object pointed to by TOKEN and return the corresponding
12150  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12151  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12152  * mapping table.
12153  *
12154  * LOCKING: Take the loader lock
12155  */
12156 gpointer
12157 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12158 {
12159         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12160         MonoObject *obj;
12161         MonoClass *klass;
12162
12163         obj = lookup_dyn_token (assembly, token);
12164         if (!obj) {
12165                 if (valid_token)
12166                         g_error ("Could not find required dynamic token 0x%08x", token);
12167                 else
12168                         return NULL;
12169         }
12170
12171         if (!handle_class)
12172                 handle_class = &klass;
12173         return resolve_object (image, obj, handle_class, context);
12174 }
12175
12176 /*
12177  * ensure_complete_type:
12178  *
12179  *   Ensure that KLASS is completed if it is a dynamic type, or references
12180  * dynamic types.
12181  */
12182 static void
12183 ensure_complete_type (MonoClass *klass)
12184 {
12185         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12186                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12187
12188                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12189
12190                 // Asserting here could break a lot of code
12191                 //g_assert (klass->wastypebuilder);
12192         }
12193
12194         if (klass->generic_class) {
12195                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12196                 int i;
12197
12198                 for (i = 0; i < inst->type_argc; ++i) {
12199                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12200                 }
12201         }
12202 }
12203
12204 static gpointer
12205 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12206 {
12207         gpointer result = NULL;
12208
12209         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12210                 result = mono_string_intern ((MonoString*)obj);
12211                 *handle_class = mono_defaults.string_class;
12212                 g_assert (result);
12213         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12214                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12215                 MonoClass *mc = mono_class_from_mono_type (type);
12216                 if (!mono_class_init (mc))
12217                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12218
12219                 if (context) {
12220                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12221                         result = mono_class_from_mono_type (inflated);
12222                         mono_metadata_free_type (inflated);
12223                 } else {
12224                         result = mono_class_from_mono_type (type);
12225                 }
12226                 *handle_class = mono_defaults.typehandle_class;
12227                 g_assert (result);
12228         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12229                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12230                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12231                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12232                 result = ((MonoReflectionMethod*)obj)->method;
12233                 if (context) {
12234                         MonoError error;
12235                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12236                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12237                 }
12238                 *handle_class = mono_defaults.methodhandle_class;
12239                 g_assert (result);
12240         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12241                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12242                 result = mb->mhandle;
12243                 if (!result) {
12244                         /* Type is not yet created */
12245                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12246
12247                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12248
12249                         /*
12250                          * Hopefully this has been filled in by calling CreateType() on the
12251                          * TypeBuilder.
12252                          */
12253                         /*
12254                          * TODO: This won't work if the application finishes another 
12255                          * TypeBuilder instance instead of this one.
12256                          */
12257                         result = mb->mhandle;
12258                 }
12259                 if (context) {
12260                         MonoError error;
12261                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12262                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12263                 }
12264                 *handle_class = mono_defaults.methodhandle_class;
12265         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12266                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12267
12268                 result = cb->mhandle;
12269                 if (!result) {
12270                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12271
12272                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12273                         result = cb->mhandle;
12274                 }
12275                 if (context) {
12276                         MonoError error;
12277                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12278                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12279                 }
12280                 *handle_class = mono_defaults.methodhandle_class;
12281         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12282                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12283
12284                 ensure_complete_type (field->parent);
12285                 if (context) {
12286                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12287                         MonoClass *klass = mono_class_from_mono_type (inflated);
12288                         MonoClassField *inflated_field;
12289                         gpointer iter = NULL;
12290                         mono_metadata_free_type (inflated);
12291                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12292                                 if (!strcmp (field->name, inflated_field->name))
12293                                         break;
12294                         }
12295                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12296                         result = inflated_field;
12297                 } else {
12298                         result = field;
12299                 }
12300                 *handle_class = mono_defaults.fieldhandle_class;
12301                 g_assert (result);
12302         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12303                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12304                 result = fb->handle;
12305
12306                 if (!result) {
12307                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12308
12309                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12310                         result = fb->handle;
12311                 }
12312
12313                 if (fb->handle && fb->handle->parent->generic_container) {
12314                         MonoClass *klass = fb->handle->parent;
12315                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12316                         MonoClass *inflated = mono_class_from_mono_type (type);
12317
12318                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12319                         g_assert (result);
12320                         mono_metadata_free_type (type);
12321                 }
12322                 *handle_class = mono_defaults.fieldhandle_class;
12323         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12324                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12325                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12326                 MonoClass *klass;
12327
12328                 klass = type->data.klass;
12329                 if (klass->wastypebuilder) {
12330                         /* Already created */
12331                         result = klass;
12332                 }
12333                 else {
12334                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12335                         result = type->data.klass;
12336                         g_assert (result);
12337                 }
12338                 *handle_class = mono_defaults.typehandle_class;
12339         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12340                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12341                 MonoMethodSignature *sig;
12342                 int nargs, i;
12343
12344                 if (helper->arguments)
12345                         nargs = mono_array_length (helper->arguments);
12346                 else
12347                         nargs = 0;
12348
12349                 sig = mono_metadata_signature_alloc (image, nargs);
12350                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12351                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12352
12353                 if (helper->unmanaged_call_conv) { /* unmanaged */
12354                         sig->call_convention = helper->unmanaged_call_conv - 1;
12355                         sig->pinvoke = TRUE;
12356                 } else if (helper->call_conv & 0x02) {
12357                         sig->call_convention = MONO_CALL_VARARG;
12358                 } else {
12359                         sig->call_convention = MONO_CALL_DEFAULT;
12360                 }
12361
12362                 sig->param_count = nargs;
12363                 /* TODO: Copy type ? */
12364                 sig->ret = helper->return_type->type;
12365                 for (i = 0; i < nargs; ++i)
12366                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12367
12368                 result = sig;
12369                 *handle_class = NULL;
12370         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12371                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12372                 /* Already created by the managed code */
12373                 g_assert (method->mhandle);
12374                 result = method->mhandle;
12375                 *handle_class = mono_defaults.methodhandle_class;
12376         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12377                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12378                 type = mono_class_inflate_generic_type (type, context);
12379                 result = mono_class_from_mono_type (type);
12380                 *handle_class = mono_defaults.typehandle_class;
12381                 g_assert (result);
12382                 mono_metadata_free_type (type);
12383         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12384                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12385                 type = mono_class_inflate_generic_type (type, context);
12386                 result = mono_class_from_mono_type (type);
12387                 *handle_class = mono_defaults.typehandle_class;
12388                 g_assert (result);
12389                 mono_metadata_free_type (type);
12390         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12391                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12392                 MonoClass *inflated;
12393                 MonoType *type;
12394                 MonoClassField *field;
12395
12396                 if (is_sre_field_builder (mono_object_class (f->fb)))
12397                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12398                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12399                         field = ((MonoReflectionField*)f->fb)->field;
12400                 else
12401                         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)));
12402
12403                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12404                 inflated = mono_class_from_mono_type (type);
12405
12406                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12407                 ensure_complete_type (field->parent);
12408                 g_assert (result);
12409                 mono_metadata_free_type (type);
12410                 *handle_class = mono_defaults.fieldhandle_class;
12411         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12412                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12413                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12414                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12415                 MonoMethod *method;
12416
12417                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12418                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12419                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12420                         method = ((MonoReflectionMethod *)c->cb)->method;
12421                 else
12422                         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)));
12423
12424                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12425                 *handle_class = mono_defaults.methodhandle_class;
12426                 mono_metadata_free_type (type);
12427         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12428                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12429                 if (m->method_args) {
12430                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12431                         if (context) {
12432                                 MonoError error;
12433                                 result = mono_class_inflate_generic_method_checked (result, context, &error);
12434                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12435                         }
12436                 } else {
12437                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12438                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12439                         MonoMethod *method;
12440
12441                         if (is_sre_method_builder (mono_object_class (m->mb)))
12442                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12443                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12444                                 method = ((MonoReflectionMethod *)m->mb)->method;
12445                         else
12446                                 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)));
12447
12448                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12449                         mono_metadata_free_type (type);
12450                 }
12451                 *handle_class = mono_defaults.methodhandle_class;
12452         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12453                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12454                 MonoType *mtype;
12455                 MonoClass *klass;
12456                 MonoMethod *method;
12457                 gpointer iter;
12458                 char *name;
12459
12460                 mtype = mono_reflection_type_get_handle (m->parent);
12461                 klass = mono_class_from_mono_type (mtype);
12462
12463                 /* Find the method */
12464
12465                 name = mono_string_to_utf8 (m->name);
12466                 iter = NULL;
12467                 while ((method = mono_class_get_methods (klass, &iter))) {
12468                         if (!strcmp (method->name, name))
12469                                 break;
12470                 }
12471                 g_free (name);
12472
12473                 // FIXME:
12474                 g_assert (method);
12475                 // FIXME: Check parameters/return value etc. match
12476
12477                 result = method;
12478                 *handle_class = mono_defaults.methodhandle_class;
12479         } else if (is_sre_array (mono_object_get_class(obj)) ||
12480                                 is_sre_byref (mono_object_get_class(obj)) ||
12481                                 is_sre_pointer (mono_object_get_class(obj))) {
12482                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12483                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12484
12485                 if (context) {
12486                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12487                         result = mono_class_from_mono_type (inflated);
12488                         mono_metadata_free_type (inflated);
12489                 } else {
12490                         result = mono_class_from_mono_type (type);
12491                 }
12492                 *handle_class = mono_defaults.typehandle_class;
12493         } else {
12494                 g_print ("%s\n", obj->vtable->klass->name);
12495                 g_assert_not_reached ();
12496         }
12497         return result;
12498 }
12499
12500 #else /* DISABLE_REFLECTION_EMIT */
12501
12502 MonoArray*
12503 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12504 {
12505         g_assert_not_reached ();
12506         return NULL;
12507 }
12508
12509 void
12510 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12511 {
12512         g_assert_not_reached ();
12513 }
12514
12515 void
12516 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12517 {
12518         g_assert_not_reached ();
12519 }
12520
12521 void
12522 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12523 {
12524         g_assert_not_reached ();
12525 }
12526
12527 void
12528 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12529 {
12530         g_assert_not_reached ();
12531 }
12532
12533 void
12534 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12535 {
12536         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12537 }
12538
12539 void
12540 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12541 {
12542         g_assert_not_reached ();
12543 }
12544
12545 void
12546 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12547 {
12548         g_assert_not_reached ();
12549 }
12550
12551 MonoReflectionModule *
12552 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12553 {
12554         g_assert_not_reached ();
12555         return NULL;
12556 }
12557
12558 guint32
12559 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12560 {
12561         g_assert_not_reached ();
12562         return 0;
12563 }
12564
12565 guint32
12566 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12567 {
12568         g_assert_not_reached ();
12569         return 0;
12570 }
12571
12572 guint32
12573 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12574                                                  gboolean create_open_instance, gboolean register_token)
12575 {
12576         g_assert_not_reached ();
12577         return 0;
12578 }
12579
12580 void
12581 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12582 {
12583 }
12584
12585 void
12586 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12587 {
12588         g_assert_not_reached ();
12589 }
12590
12591 void
12592 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12593 {
12594         *overrides = NULL;
12595         *num_overrides = 0;
12596 }
12597
12598 MonoReflectionEvent *
12599 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12600 {
12601         g_assert_not_reached ();
12602         return NULL;
12603 }
12604
12605 MonoReflectionType*
12606 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12607 {
12608         g_assert_not_reached ();
12609         return NULL;
12610 }
12611
12612 void
12613 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12614 {
12615         g_assert_not_reached ();
12616 }
12617
12618 MonoArray *
12619 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12620 {
12621         g_assert_not_reached ();
12622         return NULL;
12623 }
12624
12625 MonoArray *
12626 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12627 {
12628         g_assert_not_reached ();
12629         return NULL;
12630 }
12631
12632 void 
12633 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12634 {
12635 }
12636
12637 gpointer
12638 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12639 {
12640         return NULL;
12641 }
12642
12643 MonoType*
12644 mono_reflection_type_get_handle (MonoReflectionType* ref)
12645 {
12646         if (!ref)
12647                 return NULL;
12648         return ref->type;
12649 }
12650
12651 void
12652 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12653 {
12654         g_assert_not_reached ();
12655 }
12656
12657 #endif /* DISABLE_REFLECTION_EMIT */
12658
12659 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12660 const static guint32 declsec_flags_map[] = {
12661         0x00000000,                                     /* empty */
12662         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12663         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12664         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12665         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12666         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12667         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12668         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12669         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12670         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12671         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12672         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12673         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12674         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12675         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12676         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12677         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12678         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12679         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12680 };
12681
12682 /*
12683  * Returns flags that includes all available security action associated to the handle.
12684  * @token: metadata token (either for a class or a method)
12685  * @image: image where resides the metadata.
12686  */
12687 static guint32
12688 mono_declsec_get_flags (MonoImage *image, guint32 token)
12689 {
12690         int index = mono_metadata_declsec_from_index (image, token);
12691         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12692         guint32 result = 0;
12693         guint32 action;
12694         int i;
12695
12696         /* HasSecurity can be present for other, not specially encoded, attributes,
12697            e.g. SuppressUnmanagedCodeSecurityAttribute */
12698         if (index < 0)
12699                 return 0;
12700
12701         for (i = index; i < t->rows; i++) {
12702                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12703
12704                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12705                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12706                         break;
12707
12708                 action = cols [MONO_DECL_SECURITY_ACTION];
12709                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12710                         result |= declsec_flags_map [action];
12711                 } else {
12712                         g_assert_not_reached ();
12713                 }
12714         }
12715         return result;
12716 }
12717
12718 /*
12719  * Get the security actions (in the form of flags) associated with the specified method.
12720  *
12721  * @method: The method for which we want the declarative security flags.
12722  * Return the declarative security flags for the method (only).
12723  *
12724  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12725  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12726  */
12727 guint32
12728 mono_declsec_flags_from_method (MonoMethod *method)
12729 {
12730         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12731                 /* FIXME: No cache (for the moment) */
12732                 guint32 idx = mono_method_get_index (method);
12733                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12734                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12735                 return mono_declsec_get_flags (method->klass->image, idx);
12736         }
12737         return 0;
12738 }
12739
12740 /*
12741  * Get the security actions (in the form of flags) associated with the specified class.
12742  *
12743  * @klass: The class for which we want the declarative security flags.
12744  * Return the declarative security flags for the class.
12745  *
12746  * Note: We cache the flags inside the MonoClass structure as this will get 
12747  *       called very often (at least for each method).
12748  */
12749 guint32
12750 mono_declsec_flags_from_class (MonoClass *klass)
12751 {
12752         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12753                 if (!klass->ext || !klass->ext->declsec_flags) {
12754                         guint32 idx;
12755
12756                         idx = mono_metadata_token_index (klass->type_token);
12757                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12758                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12759                         mono_loader_lock ();
12760                         mono_class_alloc_ext (klass);
12761                         mono_loader_unlock ();
12762                         /* we cache the flags on classes */
12763                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12764                 }
12765                 return klass->ext->declsec_flags;
12766         }
12767         return 0;
12768 }
12769
12770 /*
12771  * Get the security actions (in the form of flags) associated with the specified assembly.
12772  *
12773  * @assembly: The assembly for which we want the declarative security flags.
12774  * Return the declarative security flags for the assembly.
12775  */
12776 guint32
12777 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12778 {
12779         guint32 idx = 1; /* there is only one assembly */
12780         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12781         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12782         return mono_declsec_get_flags (assembly->image, idx);
12783 }
12784
12785
12786 /*
12787  * Fill actions for the specific index (which may either be an encoded class token or
12788  * an encoded method token) from the metadata image.
12789  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12790  */
12791 static MonoBoolean
12792 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12793         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12794 {
12795         MonoBoolean result = FALSE;
12796         MonoTableInfo *t;
12797         guint32 cols [MONO_DECL_SECURITY_SIZE];
12798         int index = mono_metadata_declsec_from_index (image, token);
12799         int i;
12800
12801         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12802         for (i = index; i < t->rows; i++) {
12803                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12804
12805                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12806                         return result;
12807
12808                 /* if present only replace (class) permissions with method permissions */
12809                 /* if empty accept either class or method permissions */
12810                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12811                         if (!actions->demand.blob) {
12812                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12813                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12814                                 actions->demand.blob = (char*) (blob + 2);
12815                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12816                                 result = TRUE;
12817                         }
12818                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12819                         if (!actions->noncasdemand.blob) {
12820                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12821                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12822                                 actions->noncasdemand.blob = (char*) (blob + 2);
12823                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12824                                 result = TRUE;
12825                         }
12826                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12827                         if (!actions->demandchoice.blob) {
12828                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12829                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12830                                 actions->demandchoice.blob = (char*) (blob + 2);
12831                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12832                                 result = TRUE;
12833                         }
12834                 }
12835         }
12836
12837         return result;
12838 }
12839
12840 static MonoBoolean
12841 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12842         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12843 {
12844         guint32 idx = mono_metadata_token_index (klass->type_token);
12845         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12846         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12847         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12848 }
12849
12850 static MonoBoolean
12851 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12852         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12853 {
12854         guint32 idx = mono_method_get_index (method);
12855         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12856         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12857         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12858 }
12859
12860 /*
12861  * Collect all actions (that requires to generate code in mini) assigned for
12862  * the specified method.
12863  * Note: Don't use the content of actions if the function return FALSE.
12864  */
12865 MonoBoolean
12866 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12867 {
12868         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12869                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12870         MonoBoolean result = FALSE;
12871         guint32 flags;
12872
12873         /* quick exit if no declarative security is present in the metadata */
12874         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12875                 return FALSE;
12876
12877         /* we want the original as the wrapper is "free" of the security informations */
12878         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12879                 method = mono_marshal_method_from_wrapper (method);
12880                 if (!method)
12881                         return FALSE;
12882         }
12883
12884         /* First we look for method-level attributes */
12885         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12886                 mono_class_init (method->klass);
12887                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12888
12889                 result = mono_declsec_get_method_demands_params (method, demands, 
12890                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12891         }
12892
12893         /* Here we use (or create) the class declarative cache to look for demands */
12894         flags = mono_declsec_flags_from_class (method->klass);
12895         if (flags & mask) {
12896                 if (!result) {
12897                         mono_class_init (method->klass);
12898                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12899                 }
12900                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12901                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12902         }
12903
12904         /* The boolean return value is used as a shortcut in case nothing needs to
12905            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12906         return result;
12907 }
12908
12909
12910 /*
12911  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12912  *
12913  * Note: Don't use the content of actions if the function return FALSE.
12914  */
12915 MonoBoolean
12916 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12917 {
12918         MonoBoolean result = FALSE;
12919         guint32 flags;
12920
12921         /* quick exit if no declarative security is present in the metadata */
12922         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12923                 return FALSE;
12924
12925         /* we want the original as the wrapper is "free" of the security informations */
12926         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12927                 method = mono_marshal_method_from_wrapper (method);
12928                 if (!method)
12929                         return FALSE;
12930         }
12931
12932         /* results are independant - zeroize both */
12933         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12934         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12935
12936         /* First we look for method-level attributes */
12937         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12938                 mono_class_init (method->klass);
12939
12940                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12941                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12942         }
12943
12944         /* Here we use (or create) the class declarative cache to look for demands */
12945         flags = mono_declsec_flags_from_class (method->klass);
12946         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12947                 mono_class_init (method->klass);
12948
12949                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12950                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12951         }
12952
12953         return result;
12954 }
12955
12956 /*
12957  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12958  *
12959  * @klass       The inherited class - this is the class that provides the security check (attributes)
12960  * @demans      
12961  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12962  * 
12963  * Note: Don't use the content of actions if the function return FALSE.
12964  */
12965 MonoBoolean
12966 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12967 {
12968         MonoBoolean result = FALSE;
12969         guint32 flags;
12970
12971         /* quick exit if no declarative security is present in the metadata */
12972         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12973                 return FALSE;
12974
12975         /* Here we use (or create) the class declarative cache to look for demands */
12976         flags = mono_declsec_flags_from_class (klass);
12977         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12978                 mono_class_init (klass);
12979                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12980
12981                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12982                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12983         }
12984
12985         return result;
12986 }
12987
12988 /*
12989  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12990  *
12991  * Note: Don't use the content of actions if the function return FALSE.
12992  */
12993 MonoBoolean
12994 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12995 {
12996         /* quick exit if no declarative security is present in the metadata */
12997         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12998                 return FALSE;
12999
13000         /* we want the original as the wrapper is "free" of the security informations */
13001         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13002                 method = mono_marshal_method_from_wrapper (method);
13003                 if (!method)
13004                         return FALSE;
13005         }
13006
13007         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13008                 mono_class_init (method->klass);
13009                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13010
13011                 return mono_declsec_get_method_demands_params (method, demands, 
13012                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13013         }
13014         return FALSE;
13015 }
13016
13017
13018 static MonoBoolean
13019 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13020 {
13021         guint32 cols [MONO_DECL_SECURITY_SIZE];
13022         MonoTableInfo *t;
13023         int i;
13024
13025         int index = mono_metadata_declsec_from_index (image, token);
13026         if (index == -1)
13027                 return FALSE;
13028
13029         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13030         for (i = index; i < t->rows; i++) {
13031                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13032
13033                 /* shortcut - index are ordered */
13034                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13035                         return FALSE;
13036
13037                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13038                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13039                         entry->blob = (char*) (metadata + 2);
13040                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13041                         return TRUE;
13042                 }
13043         }
13044
13045         return FALSE;
13046 }
13047
13048 MonoBoolean
13049 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13050 {
13051         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13052                 guint32 idx = mono_method_get_index (method);
13053                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13054                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13055                 return get_declsec_action (method->klass->image, idx, action, entry);
13056         }
13057         return FALSE;
13058 }
13059
13060 MonoBoolean
13061 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13062 {
13063         /* use cache */
13064         guint32 flags = mono_declsec_flags_from_class (klass);
13065         if (declsec_flags_map [action] & flags) {
13066                 guint32 idx = mono_metadata_token_index (klass->type_token);
13067                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13068                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13069                 return get_declsec_action (klass->image, idx, action, entry);
13070         }
13071         return FALSE;
13072 }
13073
13074 MonoBoolean
13075 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13076 {
13077         guint32 idx = 1; /* there is only one assembly */
13078         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13079         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13080
13081         return get_declsec_action (assembly->image, idx, action, entry);
13082 }
13083
13084 gboolean
13085 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13086 {
13087         MonoObject *res, *exc;
13088         void *params [1];
13089         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13090         static MonoMethod *method = NULL;
13091
13092         if (!System_Reflection_Emit_TypeBuilder) {
13093                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13094                 g_assert (System_Reflection_Emit_TypeBuilder);
13095         }
13096         if (method == NULL) {
13097                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13098                 g_assert (method);
13099         }
13100
13101         /* 
13102          * The result of mono_type_get_object () might be a System.MonoType but we
13103          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13104          */
13105         g_assert (mono_class_get_ref_info (klass));
13106         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13107
13108         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13109
13110         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13111         if (exc)
13112                 return FALSE;
13113         else
13114                 return *(MonoBoolean*)mono_object_unbox (res);
13115 }
13116
13117 /**
13118  * mono_reflection_type_get_type:
13119  * @reftype: the System.Type object
13120  *
13121  * Returns the MonoType* associated with the C# System.Type object @reftype.
13122  */
13123 MonoType*
13124 mono_reflection_type_get_type (MonoReflectionType *reftype)
13125 {
13126         g_assert (reftype);
13127
13128         return mono_reflection_type_get_handle (reftype);
13129 }
13130
13131 /**
13132  * mono_reflection_assembly_get_assembly:
13133  * @refassembly: the System.Reflection.Assembly object
13134  *
13135  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13136  */
13137 MonoAssembly*
13138 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13139 {
13140         g_assert (refassembly);
13141
13142         return refassembly->assembly;
13143 }
13144